text:
/* Copyright (c) 2009-2013, Fortylines LLC
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
     * Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
     * Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
     * Neither the name of fortylines nor the
       names of its contributors may be used to endorse or promote products
       derived from this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY Fortylines LLC ''AS IS'' AND ANY
   EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   DISCLAIMED. IN NO EVENT SHALL Fortylines LLC BE LIABLE FOR ANY
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */

#include <string>
#include <locale>
#include <boost/date_time/local_time/local_time.hpp>
#include <Poco/Net/SMTPClientSession.h>
#include "mail.hh"
#include "markup.hh"
#include "composer.hh"

/** Parser for mailboxes

    references:
      http://en.wikipedia.org/wiki/Mbox
      see also rfc2822tok.cc

    Primary Author(s): Sebastien Mirolo <smirolo@fortylines.com>
*/
namespace tero {

urlVariable smtpHost("smtpHost",
    "host to connect to in order to send emails");
intVariable smtpPort("smtpPort",
    "port to connect to in order to send emails");
sessionVariable smtpLogin("smtpLogin",
    "login to the $smtpHost:$smtpPort");
sessionVariable smtpPassword("smtpPassword",
    "password $smtpHost:$smtpPort");
}

namespace {

    void validate( const tero::session& s ) {
        assert( !tero::smtpHost.value(s).empty() );
        assert( tero::smtpPort.value(s) != 0);
        assert( !tero::smtpLogin.value(s).empty() );
        assert( !tero::smtpPassword.value(s).empty() );
    }

} // anonymous

namespace tero {

void
mailAddSessionVars( boost::program_options::options_description& opts,
    boost::program_options::options_description& visible )
{
    using namespace boost::program_options;

    options_description localOptions("mail");
    localOptions.add(smtpHost.option());
    localOptions.add(smtpPort.option());
    localOptions.add(smtpLogin.option());
    localOptions.add(smtpPassword.option());
    opts.add(localOptions);
}

std::string qualifiedMailAddress( const session& s, const std::string& uid ) {
    std::stringstream qualified;
    qualified << uid << '@' << domainName.value(s);
    return qualified.str();
}

void sendMail( const session& s, const Poco::Net::MailMessage& message )
{
    using namespace Poco::Net;
    validate(s);

    SMTPClientSession session(smtpHost.value(s).string(),
        smtpPort.value(s));
    session.login(SMTPClientSession::AUTH_LOGIN,
        smtpLogin.value(s),
        smtpPassword.value(s));
    session.sendMessage(message);
    session.close();
}

char noTemplate[] = "";

void sendMail( session& s,
    const std::string& recipient,
    const std::string& subject,
    const char *contentTemplate )
{
    using namespace Poco::Net;

    std::ostream& prevDisp = s.out();
    std::stringstream content;
    s.out(content);
    compose<noTemplate>(s,s.asUrl(contentTemplate));
    s.out(prevDisp);

    MailMessage message;
    message.setSubject(subject);
    message.setSender(qualifiedMailAddress(s,"no-reply"));
    message.setContent(content.str(),MailMessage::ENCODING_QUOTED_PRINTABLE);
    message.addRecipient(MailRecipient(MailRecipient::PRIMARY_RECIPIENT,
            recipient));
    sendMail(s, message);
}

void mailthread::filters( const post& p ) {
    static const boost::regex titlePat("(^.*:)(.*)");

    boost::smatch m;
    if( boost::regex_match(p.title,m,titlePat) ) {
        indexMap::iterator found = indexes.find(m.str(2));
        if( found != indexes.end() ) {
            ++found->second;
        } else {
            indexes[m.str(2)] = 0;
        }
    }
}

void mailthread::flush() {
    for( indexMap::iterator idx = indexes.begin();
         idx != indexes.end(); ++idx ) {
        *ostr << idx->first << "(" << idx->second << ")" << std::endl;
    }
}

void mailAsPost::newline(const char *line, int first, int last )
{
}

void mailAsPost::token( rfc2822Token token, const char *line,
    int first, int last, bool fragment )
{
    std::string debug(&line[first],last - first);
    switch( token ) {
    case rfc2822FieldName:
        nontrivial = true;
        field = rfc2822Err;
        if( strncmp(&line[first],"Date",last - first) == 0 ) {
            field = rfc2822Time;
        } else if( strncmp(&line[first],"From",last - first) == 0 ) {
            field = rfc2822AuthorEmail;
        } else if( strncmp(&line[first],"Subject",last - first) == 0 ) {
            field = rfc2822Title;
        } else if( strncmp(&line[first],"Score",last - first) == 0 ) {
            field = extScore;
        } else {
            name = std::string(&line[first],last - first);
            name[0] = std::tolower(name[0]);
        }
        break;
    case rfc2822FieldBody: {
        nontrivial = true;
        std::string value = strip(std::string(&line[first],last - first));
        switch( field ) {
        case rfc2822Time:
            try {
                constructed.time = parse_datetime(value);
            } catch( std::exception& e ) {
                std::cerr << "unable to reconstruct time from " << value << std::endl;
            }
            break;
        case rfc2822AuthorEmail:
            constructed.author = contrib::find(extractEmailAddress(value),
                extractName(value));
            break;
        case rfc2822Title:
            constructed.title = value;
            break;
        case extScore:
            constructed.score = atoi(value.c_str());
            break;
        default: {
            if( name.compare(0, 16, "x-Profile-Google") == 0 ) {
                constructed.author->google = value;
            } else if( name.compare(0, 18, "x-Profile-Linkedin") == 0 ) {
                constructed.author->linkedin = value;
            } else {
                post::headersMap::iterator header
                    = constructed.moreHeaders.find(name);
                if( header != constructed.moreHeaders.end() ) {
                    header->second += std::string(",") + value;
                } else {
                    constructed.moreHeaders[name] = value;
                }
            }
        } break;
        }
    } break;
    case rfc2822MessageBody:
        nontrivial = true;
        constructed.content = std::string(&line[first],&line[last]);
        break;
    default:
        /* to stop gcc from complaining */
        break;
    }
}

void
mailParser::addFile( session& s, const boost::filesystem::path& filename ) const
{
    slice<char> text = s.loadtext(filename);
    char *start = text.begin();
    size_t length = text.size();
    while( length > 0 ) {
        mailAsPost listener;
        rfc2822Tokenizer tok(listener);
        size_t processed = tok.tokenize(start, length);
        start += processed;
        length -= processed;
        if( listener.nontrivial ) {
            post entry = listener.unserialized();
            entry.filename = filename;
            entry.guid = s.asUrl(filename).string();
            filter->filters(entry);
            if( stopOnFirst ) break;
        }
    }
}

void mailParser::flush( session& s ) const
{
    filter->flush();
}

void mailParserFetch( session& s, const url& name )
{
    mailthread mt(s.out());
    mailParser mp(mt);
    mp.fetch(s,s.abspath(name));
#if 0
    /* \todo Cannot flush here if we want to support feedContent calls blogEntry.
       This call will generate non-intended intermediate flushes. It might be
       useful for other parts of the system though...
     */
    filter->flush();
#endif
}

}

max_stars_repo_name: smirolo/tero

max_issues_repo_name: smirolo/tero

max_forks_repo_name: smirolo/tero


text:
#include <boost/align.hpp>

int
main ()
{
  return 0;
}

ext: cpp


text:
#ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED
#define BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED

//  Copyright Beman Dawes 2006, 2007
//  Copyright Christoper Kohlhoff 2007
//  Copyright Peter Dimov 2017-2021
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
//  See library home page at http://www.boost.org/libs/system

#include <boost/system/is_error_code_enum.hpp>
#include <boost/system/detail/error_category.hpp>
#include <boost/system/detail/error_condition.hpp>
#include <boost/system/detail/system_category.hpp>
#include <boost/system/detail/system_category_impl.hpp>
#include <boost/system/detail/interop_category.hpp>
#include <boost/system/detail/enable_if.hpp>
#include <boost/system/detail/is_same.hpp>
#include <boost/system/detail/append_int.hpp>
#include <boost/system/detail/snprintf.hpp>
#include <boost/system/detail/config.hpp>
#include <boost/assert/source_location.hpp>
#include <boost/cstdint.hpp>
#include <boost/config.hpp>
#include <ostream>
#include <new>
#include <cstdio>

#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
# include <system_error>
#endif

#if defined(BOOST_GCC) && BOOST_GCC >= 40600 && BOOST_GCC < 70000
# pragma GCC diagnostic push
//# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif

namespace boost
{

namespace system
{

//  class error_code

//  We want error_code to be a value type that can be copied without slicing
//  and without requiring heap allocation, but we also want it to have
//  polymorphic behavior based on the error category. This is achieved by
//  abstract base class error_category supplying the polymorphic behavior,
//  and error_code containing a pointer to an object of a type derived
//  from error_category.

std::size_t hash_value( error_code const & ec );

class error_code
{
private:

    friend std::size_t hash_value( error_code const & ec );

private:

    struct data
    {
        int val_;
        const error_category * cat_;
    };

    union
    {
        data d1_;
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
        unsigned char d2_[ sizeof(std::error_code) ];
#endif
    };

    // 0: default constructed, d1_ value initialized
    // 1: holds std::error_code in d2_
    // 2: holds error code in d1_, failed == false
    // 3: holds error code in d1_, failed == true
    // >3: pointer to source_location, failed_ in lsb
    boost::uintptr_t lc_flags_;

public:

    // constructors:

    BOOST_SYSTEM_CONSTEXPR error_code() BOOST_NOEXCEPT:
        d1_(), lc_flags_( 0 )
    {
    }

    BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_NOEXCEPT:
        d1_(), lc_flags_( 2 + detail::failed_impl( val, cat ) )
    {
        d1_.val_ = val;
        d1_.cat_ = &cat;
    }

    error_code( int val, const error_category & cat, source_location const * loc ) BOOST_NOEXCEPT:
        d1_(), lc_flags_( ( loc? reinterpret_cast<boost::uintptr_t>( loc ): 2 ) | +detail::failed_impl( val, cat ) )
    {
        d1_.val_ = val;
        d1_.cat_ = &cat;
    }

    template<class ErrorCodeEnum> BOOST_SYSTEM_CONSTEXPR error_code( ErrorCodeEnum e,
        typename detail::enable_if<
            is_error_code_enum<ErrorCodeEnum>::value
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
            || std::is_error_code_enum<ErrorCodeEnum>::value
#endif
        >::type* = 0 ) BOOST_NOEXCEPT: d1_(), lc_flags_( 0 )
    {
        *this = make_error_code( e );
    }

    template<class ErrorCodeEnum> error_code( ErrorCodeEnum e, source_location const * loc,
        typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value>::type* = 0 ) BOOST_NOEXCEPT:
        d1_(), lc_flags_( 0 )
    {
        error_code e2 = make_error_code( e );

        if( e2.lc_flags_ == 0 || e2.lc_flags_ == 1 )
        {
            *this = e2;
        }
        else
        {
            *this = error_code( e2.d1_.val_, *e2.d1_.cat_, loc );
        }
    }

#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

    error_code( std::error_code const& ec ) BOOST_NOEXCEPT:
        lc_flags_( 1 )
    {
        ::new( d2_ ) std::error_code( ec );
    }

#endif

    // modifiers:

    BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_NOEXCEPT
    {
        *this = error_code( val, cat );
    }

    void assign( int val, const error_category & cat, source_location const * loc ) BOOST_NOEXCEPT
    {
        *this = error_code( val, cat, loc );
    }

    template<typename ErrorCodeEnum>
        BOOST_SYSTEM_CONSTEXPR typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, error_code>::type &
        operator=( ErrorCodeEnum val ) BOOST_NOEXCEPT
    {
        *this = make_error_code( val );
        return *this;
    }

    template<typename ErrorCodeEnum>
        typename detail::enable_if<is_error_code_enum<ErrorCodeEnum>::value, void>::type
        assign( ErrorCodeEnum val, source_location const * loc ) BOOST_NOEXCEPT
    {
        *this = error_code( val, loc );
    }

    BOOST_SYSTEM_CONSTEXPR void clear() BOOST_NOEXCEPT
    {
        *this = error_code();
    }

    // observers:

    BOOST_SYSTEM_CONSTEXPR int value() const BOOST_NOEXCEPT
    {
        if( lc_flags_ != 1 )
        {
            return d1_.val_;
        }
        else
        {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

            std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
            return ec.value() + 1000 * static_cast<unsigned>( reinterpret_cast<boost::uintptr_t>( &ec.category() ) % 2097143 ); // 2^21-9, prime
#else

            return -1;
#endif
        }
    }

    BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_NOEXCEPT
    {
        if( lc_flags_ == 0 )
        {
            return system_category();
        }
        else if( lc_flags_ == 1 )
        {
            return detail::interop_category();
        }
        else
        {
            return *d1_.cat_;
        }
    }

    // deprecated?
    error_condition default_error_condition() const BOOST_NOEXCEPT
    {
        return category().default_error_condition( value() );
    }

    std::string message() const
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

        if( lc_flags_ == 1 )
        {
            std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
            return ec.message();
        }

#endif

        return category().message( value() );
    }

    char const * message( char * buffer, std::size_t len ) const BOOST_NOEXCEPT
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
        if( lc_flags_ == 1 )
        {
#if !defined(BOOST_NO_EXCEPTIONS)
            try
#endif
            {
                std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
                detail::snprintf( buffer, len, "%s", ec.message().c_str() );
                return buffer;
            }
#if !defined(BOOST_NO_EXCEPTIONS)
            catch( ... )
            {
            }
#endif
        }
#endif

        return category().message( value(), buffer, len );
    }

    BOOST_SYSTEM_CONSTEXPR bool failed() const BOOST_NOEXCEPT
    {
        if( lc_flags_ & 1 )
        {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)
            if( lc_flags_ == 1 )
            {
                std::error_code const& ec = *reinterpret_cast<std::error_code const*>( d2_ );
                return ec.value() != 0;
            }
#endif
            return true;
        }
        else
        {
            return false;
        }
    }

#if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)

    BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT  // true if error
    {
        return failed();
    }

#else

    typedef void (*unspecified_bool_type)();
    static void unspecified_bool_true() {}

    BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const  BOOST_NOEXCEPT // true if error
    {
        return failed()? unspecified_bool_true: 0;
    }

    BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_NOEXCEPT // true if no error
    {
        return !failed();
    }

#endif

    bool has_location() const BOOST_NOEXCEPT
    {
        return lc_flags_ >= 4;
    }

    source_location const & location() const BOOST_NOEXCEPT
    {
        BOOST_STATIC_CONSTEXPR source_location loc;
        return lc_flags_ >= 4? *reinterpret_cast<source_location const*>( lc_flags_ &~ static_cast<boost::uintptr_t>( 1 ) ): loc;
    }

    // relationals:

private:

    // private equality for use in error_category::equivalent

    friend class error_category;

    BOOST_SYSTEM_CONSTEXPR bool equals( int val, error_category const& cat ) const BOOST_NOEXCEPT
    {
        if( lc_flags_ == 0 )
        {
            return val == 0 && cat.id_ == detail::system_category_id;
        }
        else if( lc_flags_ == 1 )
        {
            return cat.id_ == detail::interop_category_id && val == value();
        }
        else
        {
            return val == d1_.val_ && cat == *d1_.cat_;
        }
    }

public:

    //  the more symmetrical non-member syntax allows enum
    //  conversions work for both rhs and lhs.

    BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

        if( lhs.lc_flags_ == 1 && rhs.lc_flags_ == 1 )
        {
            std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
            std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );

            return e1 == e2;
        }
        else
#endif
        {
            return lhs.value() == rhs.value() && lhs.category() == rhs.category();
        }
    }

    BOOST_SYSTEM_CONSTEXPR inline friend bool operator<( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

        if( lhs.lc_flags_ == 1 && rhs.lc_flags_ == 1 )
        {
            std::error_code const& e1 = *reinterpret_cast<std::error_code const*>( lhs.d2_ );
            std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( rhs.d2_ );

            return e1 < e2;
        }
        else
#endif
        {
            return lhs.category() < rhs.category() || (lhs.category() == rhs.category() && lhs.value() < rhs.value());
        }
    }

    BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    inline friend bool operator==( const error_code & code, const error_condition & condition ) BOOST_NOEXCEPT
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

        if( code.lc_flags_ == 1 )
        {
            return static_cast<std::error_code>( code ) == static_cast<std::error_condition>( condition );
        }
        else

#endif
        {
            return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() );
        }
    }

    inline friend bool operator==( const error_condition & condition, const error_code & code ) BOOST_NOEXCEPT
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

        if( code.lc_flags_ == 1 )
        {
            return static_cast<std::error_code>( code ) == static_cast<std::error_condition>( condition );
        }
        else

#endif
        {
            return code.category().equivalent( code.value(), condition ) || condition.category().equivalent( code, condition.value() );
        }
    }

    inline friend bool operator!=( const error_code & lhs, const error_condition & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    inline friend bool operator!=( const error_condition & lhs, const error_code & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

    inline friend bool operator==( std::error_code const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return lhs == static_cast< std::error_code >( rhs );
    }

    inline friend bool operator==( error_code const & lhs, std::error_code const & rhs ) BOOST_NOEXCEPT
    {
        return static_cast< std::error_code >( lhs ) == rhs;
    }

    inline friend bool operator!=( std::error_code const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    inline friend bool operator!=( error_code const & lhs, std::error_code const & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    //

    template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
    inline friend bool operator==( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
    {
        return lhs == make_error_condition( rhs );
    }

    template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
    inline friend bool operator==( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return make_error_condition( lhs ) == rhs;
    }

    template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
    inline friend bool operator!=( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    template<class E, class N = typename detail::enable_if<std::is_error_condition_enum<E>::value>::type>
    inline friend bool operator!=( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    //

    template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
    BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
    {
        return lhs == make_error_code( rhs );
    }

    template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
    BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return make_error_code( lhs ) == rhs;
    }

    template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
    BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( error_code const & lhs, E rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    template<class E, class N1 = void, class N2 = typename detail::enable_if<std::is_error_code_enum<E>::value>::type>
    BOOST_SYSTEM_CONSTEXPR inline friend bool operator!=( E lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

#if defined(BOOST_SYSTEM_CLANG_6)

    inline friend bool operator==( error_code const & lhs, std::error_condition const & rhs ) BOOST_NOEXCEPT
    {
        return static_cast< std::error_code >( lhs ) == rhs;
    }

    inline friend bool operator==( std::error_condition const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return lhs == static_cast< std::error_code >( rhs );
    }

    inline friend bool operator!=( error_code const & lhs, std::error_condition const & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

    inline friend bool operator!=( std::error_condition const & lhs, error_code const & rhs ) BOOST_NOEXCEPT
    {
        return !( lhs == rhs );
    }

#endif

    // conversions

    operator std::error_code () const
    {
        if( lc_flags_ == 1 )
        {
            return *reinterpret_cast<std::error_code const*>( d2_ );
        }
        else if( lc_flags_ == 0 )
        {
// This condition must be the same as the one in error_category_impl.hpp
#if defined(__CYGWIN__) || defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER == 1800) || (defined(BOOST_GCC) && BOOST_GCC < 50000)

            return std::error_code( 0, boost::system::system_category() );

#else

            return std::error_code();

#endif
        }
        else
        {
            return std::error_code( d1_.val_, *d1_.cat_ );
        }
    }

    operator std::error_code ()
    {
        return const_cast<error_code const&>( *this );
    }

    template<class T,
      class E = typename detail::enable_if<detail::is_same<T, std::error_code>::value>::type>
      operator T& ()
    {
        if( lc_flags_ != 1 )
        {
            std::error_code e2( *this );
            ::new( d2_ ) std::error_code( e2 );
            lc_flags_ = 1;
        }

        return *reinterpret_cast<std::error_code*>( d2_ );
    }

#if defined(BOOST_SYSTEM_CLANG_6)

    template<class T,
      class E = typename std::enable_if<std::is_same<T, std::error_code>::value>::type>
      operator T const& () = delete;

#endif

#endif

    std::string to_string() const
    {
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

        if( lc_flags_ == 1 )
        {
            std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( d2_ );

            std::string r( "std:" );
            r += e2.category().name();
            detail::append_int( r, e2.value() );

            return r;
        }
        else
#endif
        {
            std::string r = category().name();
            detail::append_int( r, value() );
            return r;
        }
    }

    template<class Ch, class Tr>
        inline friend std::basic_ostream<Ch, Tr>&
        operator<< (std::basic_ostream<Ch, Tr>& os, error_code const & ec)
    {
        return os << ec.to_string();
    }

    std::string what() const
    {
        std::string r = message();

        r += " [";
        r += to_string();

        if( has_location() )
        {
            r += " at ";
            r += location().to_string();
        }

        r += "]";
        return r;
    }
};

inline std::size_t hash_value( error_code const & ec )
{
#if defined(BOOST_SYSTEM_HAS_SYSTEM_ERROR)

    if( ec.lc_flags_ == 1 )
    {
        std::error_code const& e2 = *reinterpret_cast<std::error_code const*>( ec.d2_ );
        return std::hash<std::error_code>()( e2 );
    }

#endif

    error_category const & cat = ec.category();

    boost::ulong_long_type id_ = cat.id_;

    if( id_ == 0 )
    {
        id_ = reinterpret_cast<boost::uintptr_t>( &cat );
    }

    boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
    boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;

    // id

    hv ^= id_;
    hv *= prime;

    // value

    hv ^= static_cast<unsigned>( ec.value() );
    hv *= prime;

    return static_cast<std::size_t>( hv );
}

} // namespace system

} // namespace boost

#if defined(BOOST_GCC) && BOOST_GCC >= 40600 && BOOST_GCC < 70000
# pragma GCC diagnostic pop
#endif

#endif // #ifndef BOOST_SYSTEM_DETAIL_ERROR_CODE_HPP_INCLUDED

ext: hpp

max_stars_repo_name: robalexclark/SilveR-Dev

max_issues_repo_name: robalexclark/SilveR-Dev

max_forks_repo_name: robalexclark/SilveR-Dev


text:
/**
 * @file test_finalSelectionKernelRegressionLCB.cpp
 * @brief This file defines the test cases for the final selection kernel regression LCB policy.
 *
 * @copyright Copyright (c) 2022
 *
 */

#include <algorithm>
#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>
#include <cstddef>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "proseco_planning/action/action.h"
#include "proseco_planning/action/actionClass.h"
#include "proseco_planning/agent/agent.h"
#include "proseco_planning/config/configuration.h"
#include "proseco_planning/config/defaultConfiguration.h"
#include "proseco_planning/config/scenarioOptions.h"
#include "proseco_planning/node.h"
#include "proseco_planning/policies/final_selection/finalSelectionKernelRegressionLCB.h"
#include "proseco_planning/util/alias.h"

namespace utf = boost::unit_test;
using namespace proseco_planning;

struct ConfigFixture {
  ConfigFixture() { Config::create(config::scenarioSimple, config::optionsSimple); }
  ~ConfigFixture() { Config::get()->reset(); }
};

struct FinalSelectionKernelRegressionLCBFixture : ConfigFixture, FinalSelectionKernelRegressionLCB {
  FinalSelectionKernelRegressionLCBFixture() : FinalSelectionKernelRegressionLCB("") {}
};

BOOST_FIXTURE_TEST_SUITE(finalSelectionKernelRegressionLCB,
                         FinalSelectionKernelRegressionLCBFixture)

// ----------------------------------------------------------------
// test cases for kernels
// ----------------------------------------------------------------

BOOST_AUTO_TEST_CASE(euclidean_kernel_for_actions, *utf::tolerance(0.00001f)) {
  m_gammaAction = 1.f;

  ActionPtr action_0_0     = std::make_shared<Action>(0.f, 0.f);
  ActionPtr action_1_0     = std::make_shared<Action>(1.f, 0.f);
  ActionPtr action_0_1     = std::make_shared<Action>(0.f, 1.f);
  ActionPtr action_1_1     = std::make_shared<Action>(1.f, 1.f);
  ActionPtr action_m1_0    = std::make_shared<Action>(-1.f, 0.f);
  ActionPtr action_0_m1    = std::make_shared<Action>(0.f, -1.f);
  ActionPtr action_m1_m1   = std::make_shared<Action>(-1.f, -1.f);
  ActionPtr action_0p5_0p5 = std::make_shared<Action>(0.5f, 0.5f);

  // identity
  BOOST_TEST(Action::getSimilarity(action_0_0, action_0_0, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_1_0, action_1_0, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_0_1, action_0_1, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_1_1, action_1_1, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_m1_0, action_m1_0, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_0_m1, action_0_m1, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_m1_m1, action_m1_m1, m_gammaAction) == 1.f);
  BOOST_TEST(Action::getSimilarity(action_0p5_0p5, action_0p5_0p5, m_gammaAction) == 1.f);

  BOOST_TEST(Action::getSimilarity(action_0_0, action_1_1, m_gammaAction) == 0.1353352f);
  BOOST_TEST(Action::getSimilarity(action_1_1, action_0p5_0p5, m_gammaAction) == 0.6065306f);
  BOOST_TEST(Action::getSimilarity(action_m1_m1, action_0p5_0p5, m_gammaAction) == 0.0111089f);

  // symmetry
  BOOST_TEST(Action::getSimilarity(action_0_0, action_1_0, m_gammaAction) == 0.3678794f);
  BOOST_TEST(Action::getSimilarity(action_1_0, action_0_0, m_gammaAction) == 0.3678794f);
}

BOOST_AUTO_TEST_CASE(manhattan_kernel_for_action_classes, *utf::tolerance(0.00001f)) {
  m_gammaActionClass = 1.f;

  using ac = ActionClass;

  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::DO_NOTHING) == 1.f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::ACCELERATE) == 0.3678794f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::DECELERATE) == 0.3678794f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::CHANGE_LEFT) == 0.3678794f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::CHANGE_RIGHT) == 0.3678794f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::CHANGE_LEFT_FAST) == 0.1353352f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::CHANGE_LEFT_SLOW) == 0.1353352f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::CHANGE_RIGHT_FAST) == 0.1353352f);
  BOOST_TEST(useManhattanKernel(ac::DO_NOTHING, ac::CHANGE_RIGHT_SLOW) == 0.1353352f);

  BOOST_TEST(useManhattanKernel(ac::CHANGE_LEFT_SLOW, ac::CHANGE_LEFT_FAST) == 0.1353352f);
  BOOST_TEST(useManhattanKernel(ac::CHANGE_LEFT_SLOW, ac::CHANGE_RIGHT_SLOW) == 0.1353352f);
  BOOST_TEST(useManhattanKernel(ac::CHANGE_LEFT_SLOW, ac::ACCELERATE) == 0.0497870f);
  BOOST_TEST(useManhattanKernel(ac::CHANGE_RIGHT_FAST, ac::DECELERATE) == 0.0497870f);

  BOOST_TEST(useManhattanKernel(ac::CHANGE_LEFT_SLOW, ac::CHANGE_RIGHT_FAST) == 0.0183156f);
  BOOST_TEST(useManhattanKernel(ac::CHANGE_RIGHT_FAST, ac::CHANGE_LEFT_SLOW) == 0.0183156f);
  BOOST_TEST(useManhattanKernel(ac::CHANGE_RIGHT_SLOW, ac::CHANGE_LEFT_FAST) == 0.0183156f);
}

// ----------------------------------------------------------------
// test cases for actions
// ----------------------------------------------------------------

BOOST_AUTO_TEST_CASE(best_action_set) {
  m_moveGrouping = false;
  m_gammaAction  = 0.2f;
  m_cpAction     = 0.5f;

  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  ActionPtr accelerate      = std::make_shared<Action>(5.f, 2.f);
  ActionPtr changeLeftFast  = std::make_shared<Action>(5.f, 4.f);
  ActionPtr decelerate      = std::make_shared<Action>(-5.f, -2.f);
  ActionPtr changeRightSlow = std::make_shared<Action>(-5.f, -4.f);

  for (auto& agent : node->m_agents) {
    agent.addAvailableAction(accelerate);
    agent.addAvailableAction(changeLeftFast);
    agent.addAvailableAction(decelerate);
    agent.addAvailableAction(changeRightSlow);

    agent.m_actionValues.at(accelerate)      = 950.f;
    agent.m_actionValues.at(changeLeftFast)  = 900.f;
    agent.m_actionValues.at(decelerate)      = 100.f;
    agent.m_actionValues.at(changeRightSlow) = 1000.f;

    agent.m_actionVisits.at(accelerate)      = 20.f;
    agent.m_actionVisits.at(changeLeftFast)  = 20.f;
    agent.m_actionVisits.at(decelerate)      = 20.f;
    agent.m_actionVisits.at(changeRightSlow) = 5.f;
  }
  setBestActionSet(node);

  for (std::size_t idx = 0; idx < node->m_agents.size(); ++idx) {
    BOOST_TEST(m_bestActionSet.at(idx) == accelerate);
  }
}

BOOST_AUTO_TEST_CASE(best_action_set_random) {
  m_moveGrouping = false;
  m_gammaAction  = 0.2f;
  m_cpAction     = 0.5f;

  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  ActionPtr accelerate     = std::make_shared<Action>(5.f, 2.f);
  ActionPtr changeLeftFast = std::make_shared<Action>(5.f, 4.f);
  ActionPtr decelerate     = std::make_shared<Action>(-5.f, -2.f);

  for (auto& agent : node->m_agents) {
    agent.addAvailableAction(accelerate);
    agent.addAvailableAction(changeLeftFast);
    agent.addAvailableAction(decelerate);
  }
  setBestActionSet(node);

  for (std::size_t idx = 0; idx < node->m_agents.size(); ++idx) {
    BOOST_TEST(m_bestActionSet.at(idx) != nullptr);
  }
}

BOOST_AUTO_TEST_CASE(best_action_set_all_values_equal) {
  m_moveGrouping = false;
  m_gammaAction  = 0.2f;
  m_cpAction     = 0.5f;

  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  ActionPtr accelerate      = std::make_shared<Action>(5.f, 0.5f);
  ActionPtr changeLeftFast  = std::make_shared<Action>(5.f, 1.0f);
  ActionPtr changeRightFast = std::make_shared<Action>(5.f, -1.0f);

  for (auto& agent : node->m_agents) {
    agent.m_actionValues.insert({accelerate, 1000.f});
    agent.m_actionValues.insert({changeLeftFast, 1000.f});
    agent.m_actionValues.insert({changeRightFast, 1000.f});

    agent.m_actionVisits.insert({accelerate, 20.f});
    agent.m_actionVisits.insert({changeLeftFast, 20.f});
    agent.m_actionVisits.insert({changeRightFast, 20.f});
  }
  setBestActionSet(node);

  for (std::size_t idx = 0; idx < node->m_agents.size(); ++idx) {
    BOOST_TEST(m_bestActionSet.at(idx) == accelerate);
  }
}

BOOST_AUTO_TEST_CASE(best_action_set_with_move_grouping) {
  m_moveGrouping = true;
  m_gammaAction  = 0.2f;
  m_cpAction     = 0.5f;

  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  ActionPtr accelerate     = std::make_shared<Action>(ActionClass::ACCELERATE, 5.f, 2.f);
  ActionPtr changeLeftFast = std::make_shared<Action>(ActionClass::CHANGE_LEFT_FAST, 5.f, 4.f);
  ActionPtr doNothing      = std::make_shared<Action>(ActionClass::DO_NOTHING, 0.f, 0.f);

  m_bestActionClassSet.clear();

  for (auto& agent : node->m_agents) {
    m_bestActionClassSet.push_back(ActionClass::DO_NOTHING);

    agent.m_actionValues.insert({accelerate, 1000.f});
    agent.m_actionValues.insert({changeLeftFast, 1000.f});
    agent.m_actionValues.insert({doNothing, 500.f});

    agent.m_actionVisits.insert({accelerate, 20.f});
    agent.m_actionVisits.insert({changeLeftFast, 20.f});
    agent.m_actionVisits.insert({doNothing, 5.f});
  }
  setBestActionSet(node);

  for (std::size_t idx = 0; idx < node->m_agents.size(); ++idx) {
    BOOST_TEST(m_bestActionSet.at(idx) == doNothing);
  }
}

// ----------------------------------------------------------------
// test cases for action classes
// ----------------------------------------------------------------

BOOST_AUTO_TEST_CASE(best_action_class_set) {
  m_gammaActionClass = 1.0f;
  m_cpActionClass    = 0.5f;

  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  for (auto& agent : node->m_agents) {
    agent.m_actionClassValues.insert({ActionClass::ACCELERATE, 950.f});
    agent.m_actionClassValues.insert({ActionClass::CHANGE_LEFT_FAST, 800.f});
    agent.m_actionClassValues.insert({ActionClass::DECELERATE, 100.f});
    agent.m_actionClassValues.insert({ActionClass::CHANGE_RIGHT_SLOW, 1000.f});

    agent.m_actionClassVisits.insert({ActionClass::ACCELERATE, 20.f});
    agent.m_actionClassVisits.insert({ActionClass::CHANGE_LEFT_FAST, 20.f});
    agent.m_actionClassVisits.insert({ActionClass::DECELERATE, 20.f});
    agent.m_actionClassVisits.insert({ActionClass::CHANGE_RIGHT_SLOW, 5.f});
  }
  setBestActionClass(node);

  for (std::size_t idx = 0; idx < node->m_agents.size(); ++idx) {
    BOOST_TEST((m_bestActionClassSet.at(idx) == ActionClass::ACCELERATE));
  }
}

BOOST_AUTO_TEST_CASE(best_action_class_set_random) {
  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  ActionPtr accelerate     = std::make_shared<Action>(ActionClass::ACCELERATE);
  ActionPtr changeLeftFast = std::make_shared<Action>(ActionClass::CHANGE_LEFT_FAST);
  ActionPtr decelerate     = std::make_shared<Action>(ActionClass::DECELERATE);

  for (auto& agent : node->m_agents) {
    agent.addAvailableAction(accelerate);
    agent.addAvailableAction(changeLeftFast);
    agent.addAvailableAction(decelerate);
  }
  BOOST_CHECK_NO_THROW(setBestActionClass(node));
}

BOOST_AUTO_TEST_CASE(best_action_class_set_all_values_equal) {
  m_gammaActionClass = 1.0f;
  m_cpActionClass    = 0.5f;

  auto root = std::make_unique<Node>(sOpt().agents);
  auto node = root.get();

  for (auto& agent : node->m_agents) {
    agent.m_actionClassValues.insert({ActionClass::ACCELERATE, 1000.f});
    agent.m_actionClassValues.insert({ActionClass::CHANGE_LEFT_FAST, 1000.f});
    agent.m_actionClassValues.insert({ActionClass::CHANGE_RIGHT, 1000.f});

    agent.m_actionClassVisits.insert({ActionClass::ACCELERATE, 20.f});
    agent.m_actionClassVisits.insert({ActionClass::CHANGE_LEFT_FAST, 20.f});
    agent.m_actionClassVisits.insert({ActionClass::CHANGE_RIGHT, 20.f});
  }
  setBestActionClass(node);

  for (std::size_t idx = 0; idx < node->m_agents.size(); ++idx) {
    BOOST_TEST((m_bestActionClassSet.at(idx) == ActionClass::ACCELERATE));
  }
}

BOOST_AUTO_TEST_SUITE_END()


text:
#include <boost/coroutine/all.hpp>

int main()
{
  return 0;
}

ext: cc


text:
#include <boost/foreach.hpp>

#include <base/cgal_typedefs.h>
#include <ceres/ceres.h>
#include <ceres/rotation.h>
#include <IO/fileIO.h>
#include <IO/colmapIO.h>

#include <util/helper.h>
#include <util/endian.h>
#include <util/vectorArithmetic.h>
#include <processing/pointSetProcessing.h>
#include <processing/normalAndSensorProcessing.h>

#include <rPLY/ply.h>

//// colmap util
#ifdef COLMAP
#include <util/misc.h>
#include <util/endian.h>
#include <util/ply.h>
#include <mvs/workspace.h>
#include <mvs/fusion.h>
#endif

//#include <Open3D/Open3D.h>
//#include <Open3D/Utility/IJsonConvertible.h>
//#include <CGAL/Bbox_3.h>

/////////// read colmap reconstructions ///////////
//void getSensorMap(const std::string path, std::map<int, Point>& sensorMap){

//    colmap::mvs::StereoFusionOptions options;
//    colmap::mvs::Workspace::Options workspace_options;

//    workspace_options.max_image_size = options.max_image_size;
//    workspace_options.image_as_rgb = true;
//    workspace_options.cache_size = options.cache_size;
//    workspace_options.workspace_path = path;
//    workspace_options.workspace_format = "COLMAP";
//    workspace_options.input_type = "geometric";

//    auto ws = new colmap::mvs::Workspace(workspace_options);

//    const auto& model = ws->GetModel();

//    const auto image_names = colmap::ReadTextFileLines(colmap::JoinPaths(
//        path, workspace_options.stereo_folder, "fusion.cfg"));

//    for (const auto& image_name : image_names) {
//        const int image_idx = model.GetImageIdx(image_name);
//        const auto& image = model.images.at(image_idx);

//        // get the sensor position
//        auto R = Eigen::Map<const Eigen::Matrix<float, 3, 3, Eigen::RowMajor>>(image.GetR());
//        auto T = Eigen::Map<const Eigen::Vector3f>(image.GetT());
//        Point sensor_position = eigen2Cgal(-R.transpose()*T);
////        std::cout << image_idx << " " << image_name << " " << sensor_position << std::endl;
////        std::cout << sensor_position << std::endl;
//        sensorMap[image_idx] = sensor_position;
//    }
//}

//void readColmapRecon(dirHolder& dir, dataHolder& data){
//    auto start = std::chrono::high_resolution_clock::now();
//    cout << "\nRead colmap reconstruction: " << endl;

////    const std::string vis_path = colmap::JoinPaths(dir.path, "fused.ply.vis");
//    string vis_path = dir.path + "fused.ply.vis"
//    getSensorMap(vis_path, data.sensor_map);

//    // apply transformation to register tanks and temples colmap reconstruction with tanks and temples ground truth
//    bool applyTrafo = true;
//    cout << "\t-read transformation matrix " << dir.read_file+"_trans.txt" << endl;
//    Eigen::Matrix4d transformation_matrix = importTranslationMatrix(dir.path+dir.read_file+"_trans.txt");
////    cout << "\t\t" << transformation_matrix << endl;

//    open3d::geometry::PointCloud gt_pc;
//    cout << "\t-read ground truth from " << dir.read_file + ".ply" << endl;
//    open3d::io::ReadPointCloudFromPLY(dir.path+dir.read_file+".ply",gt_pc);
////    const auto bbox = gt_pc.GetOrientedBoundingBox();
//    const auto bbox = gt_pc.GetAxisAlignedBoundingBox().Scale(1.5);

//    // read in the points from the fused and fused.vis files
//    const auto& ply_points = colmap::ReadPly(colmap::JoinPaths(dir.path, "fused.ply"));
//    fstream vis_file(vis_path, std::ios::in | std::ios::binary);
//    CHECK(vis_file.is_open()) << vis_path;
//    const size_t vis_num_points = colmap::ReadBinaryLittleEndian<uint64_t>(&vis_file);
//    CHECK_EQ(vis_num_points, ply_points.size());

//    data.points.reserve(ply_points.size());
//    vector<Eigen::Vector3d> points_eigen;
//    vector<Eigen::Vector3d> sensors_eigen;
////    vector<Eigen::Vector3d> colors_eigen;
//    for (const auto& ply_point : ply_points){

//        points_eigen.push_back(Eigen::Vector3d(ply_point.x, ply_point.y, ply_point.z));
//        Point input_point(ply_point.x, ply_point.y, ply_point.z);

//        vertex_info vinf;
//        vinf.normal = Vector(ply_point.nx, ply_point.ny, ply_point.nz);
//        // color
//        unsigned char r,g,b;
//        r = ply_point.r;
//        g = ply_point.g;
//        b = ply_point.b;
//        std::array<unsigned char, 3> col = {r,g,b};
//        vinf.color = col;

//        // make a list of visible images, sorted by the angle between the sensor_vec and the normal of the point, smallest angles first
//        int num_visible_images = colmap::ReadBinaryLittleEndian<uint32_t>(&vis_file);
//        std::vector<std::pair<double,Point>> sensor_points;
//        for (uint32_t i = 0; i < num_visible_images; ++i) {
//            const int image_idx = colmap::ReadBinaryLittleEndian<uint32_t>(&vis_file);
//            Point sensor_point = data.sensor_map.find(image_idx)->second;
//            Vector v1 = sensor_point - input_point;
//            Vector v2 = vinf.normal;
//            double angle = std::acos( v1 * v2 / std::sqrt(v1.squared_length()*v2.squared_length()));
//            if(CGAL::cross_product(v1,v2).z()<0)
//                angle = 2*M_PI-angle;
//            sensor_points.push_back(std::make_pair(angle, sensor_point));
//        }
//        sort(sensor_points.begin(), sensor_points.end(), sortSensors);

//        for(auto& sensor_position : sensor_points){
//            if(applyTrafo)
//                applyTransformation(sensor_position.second, transformation_matrix);
//            vinf.sensor_positions.push_back(sensor_position.second);
//        }
//        sensors_eigen.push_back(Eigen::Vector3d(vinf.sensor_positions[0].x(), vinf.sensor_positions[0].y(), vinf.sensor_positions[0].z()));
////        colors_eigen.push_back(Eigen::Vector3d(ply_point.x, ply_point.y, ply_point.z));
//        if(applyTrafo)
//            applyTransformation(input_point, transformation_matrix);
//        if(pointInsideBbox(input_point,bbox)){
//            data.points.push_back(input_point);
//            vinf.sensor_vec = sensor_points[0].second-input_point;
//            data.infos.push_back(vinf);
//        }

//    }

//////    // load ground truth, make a bounding box and clip the reconstruction with this bounding box
//////    const string cropfile = dir.path + dir.read_file + "_cropfile.json";
//////    cout << "\t-read cropfile " << dir.read_file + "_cropfile.json" << endl;
//////    open3d::visualization::SelectionPolygonVolume bounding_poly;
//////    open3d::io::ReadIJsonConvertible(cropfile, bounding_poly);
//////    open3d::geometry::PointCloud pc;
//////    pc.normals_ = sensors_eigen;
//////    pc.points_ = points_eigen;

//////    auto pc_transformed = pc.Transform(transformation_matrix);

//////    cout << "size before cropping: " << pc_transformed.points_.size() << endl;
//////    auto pc_cropped = bounding_poly.CropPointCloud(pc_transformed);
//////    cout << "size after cropping: " << pc_cropped->points_.size() << endl;
//////    data.points.clear(); data.infos.clear();
//////    for(int i = 0; i < pc_cropped->points_.size(); i++){
//////        data.points.push_back(Point(pc_cropped->points_[i].x(), pc_cropped->points_[i].y(), pc_cropped->points_[i].z()));
//////        vertex_info vinf;
//////        vinf.sensor_positions.push_back(Point(pc_cropped->normals_[i].x(), pc_cropped->normals_[i].y(), pc_cropped->normals_[i].z()));
//////        data.infos.push_back(vinf);
//////    }

//    auto stop = std::chrono::high_resolution_clock::now();
//    auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
//    cout << "\t-" << data.points.size() << " points read" << endl;
//    cout << "\t-" << data.sensor_map.size() << " cameras read" << endl;
////    cout << "\t-camera positions of sensor_vec which is closest to normal will be exported to scalar_x0, scalar_y0, scalar_z0" << endl;
//    cout << "\t-in " << duration.count() << "s" << endl;

//}

void readColmapFiles(dirHolder dir, dataHolder& data)
{
    auto start = std::chrono::high_resolution_clock::now();
//    cout << "\nRead colmap points from " << dir.read_file << endl;
    cout << "\nRead colmap points from " << "fused.ply" << endl;

    const auto point_file = dir.path + "fused.ply";
    const auto vis_path = dir.path + "fused.ply.vis";
    const auto cam_file = dir.path + "sparse/images.bin";
    vector<vector<int>> vis_info;

    // read Binary PLY with normal and color
    Mesh_ply aMesh;
    Import_PLY(point_file.c_str(), &aMesh);

    // read the infos
//    loadVisibilityFile(vis_file, vis_info);
    fstream vis_file(vis_path, std::ios::in | std::ios::binary);
    const size_t vis_num_points = colmap::ReadBinaryLittleEndian<uint64_t>(&vis_file);
    CHECK_EQ(vis_num_points, aMesh.mVertices.size());
    cout << "\t-read visibility information" << endl;

    getSensorMap(cam_file, data.sensor_map);
    cout << "\t-read " << data.sensor_map.size() << " images from sparse/images.bin" << endl;

    for(int k=0; k < data.sensor_map.size(); k++){
        auto current = data.sensor_map.find(k+1);
        cout << current->first << " ";
        cout << current->second << endl;
    }

    // parse the read points
    for(int i = 0; i < aMesh.mVertices.size(); i++){
        // save points
        Point pt(aMesh.mVertices[i].x, aMesh.mVertices[i].y, aMesh.mVertices[i].z);
        data.points.push_back(pt);
        // sensor
        vertex_info vinf;
        vinf.normal = Vector(aMesh.mNormals[i].x, aMesh.mNormals[i].y, aMesh.mNormals[i].z);
        // color
        if(aMesh.mvColors.size() > 0){
            unsigned char r,g,b;
            r = aMesh.mvColors[i].x * 255;
            g = aMesh.mvColors[i].y * 255;
            b = aMesh.mvColors[i].z * 255;
            std::array<unsigned char, 3> col = {r,g,b};
            vinf.color = col;
        }

        // index, e.g. used in the concatenate data function
        vinf.global_idx = i;

        // attach info to point
        int num_visible_images = colmap::ReadBinaryLittleEndian<uint32_t>(&vis_file);
        std::vector<std::pair<double,Point>> sensor_points;
        for (uint32_t i = 0; i < num_visible_images; ++i) {
            const int image_idx = colmap::ReadBinaryLittleEndian<uint32_t>(&vis_file);
            // image_idx from the fused.ply.vis and image/camera idx from the sensorMap simply are not the same
                // careful here, the colmap camera index starts at 1 not at 0!!!!
            Point sensor_point = data.sensor_map.find(image_idx)->second;
            Vector v1 = sensor_point - pt;
            Vector v2 = vinf.normal;
            double angle = std::acos( v1 * v2 / std::sqrt(v1.squared_length()*v2.squared_length()));
            if(CGAL::cross_product(v1,v2).z()<0)
                angle = 2*M_PI-angle;
            sensor_points.push_back(std::make_pair(angle, sensor_point));
        }
        sort(sensor_points.begin(), sensor_points.end(), sortSensors);
        vinf.sensor_vec = sensor_points[0].second-pt;
        for(auto& sensor_position : sensor_points){
//            if(applyTrafo)
//                applyTransformation(sensor_position.second, transformation_matrix);
            vinf.sensor_positions.push_back(sensor_position.second);
        }
        data.infos.push_back(vinf);
    }
    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::seconds>(stop - start);
    cout << "\t-parsed " << data.points.size() << " points" << endl;
    cout << "\t-in " << duration.count() << "s" << endl;
}

////////////////////////////////////////////////
//////////////// WU TENGS CODE /////////////////
////////////////////////////////////////////////
//// for colmap fused.ply.vis(binary format)
//bool loadVisibilityFile(const string pszVisFile, vector<vector<int>>& vis_info)
//{
//    FILE * fp = fopen(pszVisFile.c_str(), "rb");
//    if (fp == NULL){
//        printf("Can not open the file %s\n", pszVisFile.c_str());
//        return false;
//    }

//    uint64_t vis_num_points = 0;
//    fread(& vis_num_points, sizeof(uint64_t), 1, fp);

//    if (vis_num_points < 1){
//        printf("no visibilty information\n");
//        fclose(fp);

//        return false;
//    }

//    vis_info.reserve(vis_num_points);
//    //for (int i = 0; i < vis_num_points; ++i){
//    for (int i = 0; i < vis_num_points; i++){
//        int num_visible_images = 0;
//        fread(& num_visible_images, sizeof(uint32_t), 1, fp);

//        std::vector<int> image_view;
//        image_view.reserve(num_visible_images);
////        for (int j = 0; j < num_visible_images; ++j){
//        for (int j = 0; j < num_visible_images; j++){
//            int image_idx = 0;
//            fread(& image_idx, sizeof(uint32_t), 1, fp);
//            image_view.push_back(image_idx);
//        }
//        vis_info.push_back(image_view);
//    }

//    fclose(fp);
//    return true;
//}

// because colmap save qvec and tvec
// we need cvec
//Eigen::Vector4d NormalizeQuaternion(const Eigen::Vector4d& qvec){
//  const double norm = qvec.norm();
//  if (norm == 0) {
//    // We do not just use (1, 0, 0, 0) because that is a constant and when used
//    // for automatic differentiation that would lead to a zero derivative.
//    return Eigen::Vector4d(1.0, qvec(1), qvec(2), qvec(3));
//  } else {
//    return qvec / norm;
//  }
//}
//Eigen::Vector3d ProjectionCenterFromPose(const double* qvec,
//                                         const Eigen::Vector3d& tvec){
//  // Inverse rotation as conjugate quaternion.
////  const Eigen::Vector4d normalized_qvec = NormalizeQuaternion(qvec);
//  Eigen::Matrix<double, 3, 3, Eigen::RowMajor> R;
//  ceres::QuaternionToRotation(qvec, R.data());

////  const Eigen::Quaterniond quat(normalized_qvec(0), -normalized_qvec(1),
////                                -normalized_qvec(2), -normalized_qvec(3));
//  return -R.transpose() * tvec;
//}
// because colmap save qvec and tvec
// we need cvec
Eigen::Vector4d NormalizeQuaternion(const Eigen::Vector4d& qvec) {
  const double norm = qvec.norm();
  if (norm == 0) {
    // We do not just use (1, 0, 0, 0) because that is a constant and when used
    // for automatic differentiation that would lead to a zero derivative.
    return Eigen::Vector4d(1.0, qvec(1), qvec(2), qvec(3));
  } else {
    return qvec / norm;
  }
}

Eigen::Vector3d ProjectionCenterFromPose(const Eigen::Vector4d& qvec,
                                         const Eigen::Vector3d& tvec) {
  // Inverse rotation as conjugate quaternion.
  const Eigen::Vector4d normalized_qvec = NormalizeQuaternion(qvec);
  const Eigen::Quaterniond quat(normalized_qvec(0), -normalized_qvec(1),
                                -normalized_qvec(2), -normalized_qvec(3));
  return quat * -tvec;
}

bool getSensorMap(const string pszImageFile, map<int, Point>& image_proj_center)
{
    FILE* fp = fopen(pszImageFile.c_str(), "rb");
    if (fp == NULL){
        printf("Can not open the file %s\n", pszImageFile.c_str());
        return false;
    }

    uint64_t num_reg_images = 0;

    fread(& num_reg_images, sizeof(uint64_t), 1, fp);

    if (num_reg_images < 1){
        printf("no image information\n");
        fclose(fp);

        return true;
    }

    for (int i = 0; i < num_reg_images; ++i){
        uint32_t num_image_index = 0;
        fread(& num_image_index, sizeof(uint32_t), 1, fp);

        double qvec_array[4] = { 0 };
        fread(qvec_array, sizeof(double), 4, fp);

        double tvec_array[3] = { 0 };
        fread(tvec_array, sizeof(double), 3, fp);

        Eigen::Vector4d qvec;
        for (int j = 0; j < 4; ++j){
            qvec(j) = qvec_array[j];
        }

        Eigen::Vector3d tvec;
        for (int j = 0; j < 3; ++j){
            tvec(j) = tvec_array[j];
        }

        Eigen::Vector3d cvec = ProjectionCenterFromPose(qvec, tvec);
//        Eigen::Vector3d cvec = ProjectionCenterFromPose(qvec_array, tvec);

        Point proj_center(cvec(0), cvec(1), cvec(2));

        uint32_t num_camera_index = 0;
        fread(& num_camera_index, sizeof(uint32_t), 1, fp);

        // read char in binary
        std::string img_name;

        char name_char;
        do {
            fread(& name_char, sizeof(char), 1, fp);
            if (name_char != '\0') {
                img_name += name_char;
            }
        } while (name_char != '\0');

        uint64_t num_points2D = 0;
        fread(& num_points2D, sizeof(uint64_t), 1, fp);

        for (int j = 0; j < num_points2D; ++j){
            double xy[2] = { 0 };
            fread(xy, sizeof(double), 2, fp);

            uint64_t num_point3d_index = 0;
            fread(& num_point3d_index, sizeof(uint64_t), 1, fp);
        }

//        std::cout << num_camera_index << " " << img_name << " " << proj_center << std::endl;
        std::cout << num_image_index << " " << img_name << " " << proj_center << std::endl;

//        image_proj_center[num_camera_index] = proj_center;
        image_proj_center[num_image_index] = proj_center;

//        image_proj_center.insert(map<int, Point>::value_type(num_camera_index, proj_center));
    }
    fclose(fp);

    return true;
}

max_stars_repo_name: raphaelsulzer/mesh-tools

max_issues_repo_name: raphaelsulzer/mesh-tools

max_forks_repo_name: raphaelsulzer/mesh-tools


text:
/**
 *  @file
 *  @author     2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
 *  @copyright  Simplified BSD
 *
 *  @cond
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the FreeBSD license as published by the FreeBSD
 *  project.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 *  You should have received a copy of the FreeBSD license along with this
 *  program. If not, see <http://www.opensource.org/licenses/bsd-license>.
 *  @endcond
 */

#include "uscxml/Common.h"
#include "uscxml/util/URL.h"
#include "uscxml/util/String.h"

#include "JSCDataModel.h"

#include "uscxml/messages/Event.h"
#ifndef NO_XERCESC
#include "uscxml/util/DOM.h"
#endif
#include "uscxml/interpreter/Logging.h"

#include <vector>
#include <string>
#include <boost/algorithm/string.hpp>

#ifdef BUILD_AS_PLUGINS
#include <Pluma/Connector.hpp>
#endif

#define EVENT_STRING_OR_UNDEF(field, cond) \
JSStringRef field##Name = JSStringCreateWithUTF8CString( uscxml::fromLocaleToUtf8(#field).c_str() ); \
JSStringRef field##Val = JSStringCreateWithUTF8CString( uscxml::fromLocaleToUtf8(event.field).c_str()); \
JSObjectSetProperty(_ctx, \
                    eventObj, \
                    field##Name, \
                    (cond ? JSValueMakeString(_ctx, field##Val) : JSValueMakeUndefined(_ctx)), \
                    0, \
                    &exception); \
JSStringRelease(field##Name); \
JSStringRelease(field##Val); \
if (exception) \
    handleException(exception, std::string("event." #field ":") + "[" + event.field + "]");

using namespace XERCESC_NS;

static std::string JS2String(JSStringRef strRef) {
	if (strRef) {
		const size_t maxSize = JSStringGetMaximumUTF8CStringSize(strRef);
		std::vector<char> buffer(maxSize, 0);
		JSStringGetUTF8CString(strRef, buffer.data(), maxSize);
		return uscxml::toLocaleFromUtf8(buffer.data());
	}
	return "";
}

static std::string JS2StringAndRelease(JSStringRef strRef) {
	if (strRef) {
		const size_t maxSize = JSStringGetMaximumUTF8CStringSize(strRef);
		std::vector<char> buffer(maxSize, 0);
		JSStringGetUTF8CString(strRef, buffer.data(), maxSize);
		JSStringRelease(strRef);
		return uscxml::toLocaleFromUtf8(buffer.data());
	}
	return "";
}

#ifndef NO_XERCESC

static JSValueRef XMLString2JS(const XMLCh* input, JSContextRef context) {
	JSValueRef output;

	char* res = XERCESC_NS::XMLString::transcode(input);

	JSStringRef stringRef = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(res).c_str());
	output = JSValueMakeString(context, stringRef);
	JSStringRelease(stringRef);

	return output;
}

static XMLCh* JS2XMLString(JSValueRef input, JSContextRef context) {

	if (!JSValueIsString(context, input))
		return NULL;

	JSValueRef exception = NULL;
	JSStringRef stringInput = JSValueToStringCopy(context, input, &exception);

	XMLCh* ret = XERCESC_NS::XMLString::transcode(JS2String(stringInput).c_str());
	return(ret);
}

#include "JSCDOM.cpp.inc"
#else
#include "JSCEvent.cpp.inc"
#endif

namespace uscxml {

	static void DumpJSObject(uscxml::Logger &logger, JSContextRef ctx, JSObjectRef objRef) {
		if (objRef) {
			JSPropertyNameArrayRef properties = JSObjectCopyPropertyNames(ctx, objRef);
			size_t paramCount = JSPropertyNameArrayGetCount(properties);
			for (size_t i = 0; i < paramCount; i++) {
				logger.log(uscxml::USCXML_LOG) << JS2StringAndRelease(JSPropertyNameArrayGetNameAtIndex(properties, i)) << std::endl;
			}
		}
	}

	class JSComplexClassException : public std::runtime_error {
	public:
		JSComplexClassException() : std::runtime_error("Complex JavaScript class") {}
	};

#ifdef BUILD_AS_PLUGINS
	PLUMA_CONNECTOR
		bool pluginConnect(pluma::Host& host) {
		host.add(new JSCDataModelProvider());
		return true;
	}
#endif

	JSCDataModel::JSCDataModel() {
		_ctx = NULL;
	}

	JSCDataModel::~JSCDataModel() {
		if (_ctx)
			JSGlobalContextRelease(_ctx);
	}

	void JSCDataModel::addExtension(DataModelExtension* ext) {
#if 0
		if (_extensions.find(ext) != _extensions.end())
			return;

		ext->dm = this;
		_extensions.insert(ext);

		JSObjectRef currScope = JSContextGetGlobalObject(_ctx);
		std::list<std::string> locPath = tokenize(ext->provides(), '.');
		std::list<std::string>::iterator locIter = locPath.begin();
		while (true) {
			std::string pathComp = *locIter;
			JSStringRef pathCompJS = JSStringCreateWithUTF8CString(pathComp.c_str());

			if (++locIter != locPath.end()) {
				// just another intermediate step
				if (!JSObjectHasProperty(_ctx, currScope, pathCompJS)) {
					JSObjectSetProperty(_ctx, currScope, pathCompJS, JSObjectMake(_ctx, NULL, NULL), kJSPropertyAttributeNone, NULL);
				}
				JSValueRef newScope = JSObjectGetProperty(_ctx, currScope, pathCompJS, NULL);
				JSStringRelease(pathCompJS);

				if (JSValueIsObject(_ctx, newScope)) {
					currScope = JSValueToObject(_ctx, newScope, NULL);
				}
				else {
					JSStringRelease(pathCompJS);
					throw "Cannot add datamodel extension in non-object";
				}
			}
			else {
				// this is the function!
				JSClassRef jsExtensionClassRef = JSClassCreate(&jsExtensionClassDef);
				JSObjectRef jsExtFuncObj = JSObjectMake(_ctx, jsExtensionClassRef, ext);
				JSObjectSetProperty(_ctx, currScope, pathCompJS, jsExtFuncObj, kJSPropertyAttributeNone, NULL);

				JSStringRelease(pathCompJS);
				break;
			}
		}
#endif
	}

	JSValueRef JSCDataModel::jsExtension(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
		DataModelExtension* extension = (DataModelExtension*)JSObjectGetPrivate(function);

		JSStringRef memberRef;
		std::string memberName = "";

		if (argumentCount > 0 && JSValueIsString(ctx, arguments[0])) {
			memberRef = JSValueToStringCopy(ctx, arguments[0], exception);
			memberName = JS2StringAndRelease(memberRef);
		}

		if (argumentCount > 1) {
			Data data;
			try {
				data = ((JSCDataModel*)(extension->dm))->getValueAsData(arguments[1]);
			}
			catch (JSComplexClassException &ex) {
				ERROR_PLATFORM_THROW(ex.what());
			}
			// setter
			extension->setValueOf(memberName, data);
			return JSValueMakeNull(ctx);
		}
		if (argumentCount == 1) {
			// getter
			return ((JSCDataModel*)(extension->dm))->getDataAsValue(extension->getValueOf(memberName));
		}

		return JSValueMakeNull(ctx);
	}

	// functions need to be objects to hold private data in JSC
	JSClassDefinition JSCDataModel::jsInClassDef = { 0, 0, "In", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsIn, 0, 0, 0 };
	JSClassDefinition JSCDataModel::jsPrintClassDef = { 0, 0, "print", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsPrint, 0, 0, 0 };
	JSClassDefinition JSCDataModel::jsExtensionClassDef = { 0, 0, "Extension", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsExtension, 0, 0, 0 };

	JSClassDefinition JSCDataModel::jsIOProcessorsClassDef = { 0, 0, "ioProcessors", 0, 0, 0, 0, 0, jsIOProcessorHasProp, jsIOProcessorGetProp, 0, 0, jsIOProcessorListProps, 0, 0, 0, 0 };
	JSClassDefinition JSCDataModel::jsInvokersClassDef = { 0, 0, "invokers", 0, 0, 0, 0, 0, jsInvokerHasProp, jsInvokerGetProp, 0, 0, jsInvokerListProps, 0, 0, 0, 0 };

	std::mutex JSCDataModel::_initMutex;

#ifndef NO_XERCESC

	bool JSCNodeListHasPropertyCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
		const std::string propName = JS2String(propertyName);

		std::string base = "0123456789";
		if (propName.find_first_not_of(base) != std::string::npos) {
			return false;
		}

		size_t index = strTo<size_t>(propName);
		SwigPrivData* t = (SwigPrivData*)JSObjectGetPrivate(object);
		DOMNodeList* nodeList = (DOMNodeList*)t->swigCObject;

		if (nodeList->getLength() < index) {
			return false;
		}

		return true;
	}

	JSValueRef JSCNodeListGetPropertyCallback(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
		const std::string propName = JS2String(propertyName);

		std::string base = "0123456789";
		if (propName.find_first_not_of(base) != std::string::npos) {
			return JSValueMakeUndefined(context);
		}

		size_t index = strTo<size_t>(propName);
		SwigPrivData* t = (SwigPrivData*)JSObjectGetPrivate(object);
		DOMNodeList* nodeList = (DOMNodeList*)t->swigCObject;

		if (nodeList->getLength() < index) {
			return JSValueMakeUndefined(context);
		}

		DOMNode* node = nodeList->item(index);
		JSValueRef jsresult = SWIG_NewPointerObj(SWIG_as_voidptr(node),
			SWIG_TypeDynamicCast(SWIGTYPE_p_XERCES_CPP_NAMESPACE__DOMNode, SWIG_as_voidptrptr(&node)), 0);
		return jsresult;
	}
#endif

	std::shared_ptr<DataModelImpl> JSCDataModel::create(DataModelCallbacks* callbacks) {
		std::shared_ptr<JSCDataModel> dm(new JSCDataModel());
		dm->_callbacks = callbacks;
		dm->setup();
		return dm;
	}

	void JSCDataModel::setup() {
		_ctx = JSGlobalContextCreate(NULL);

#ifndef NO_XERCESC
		JSObjectRef exports;

		// register subscript operator with nodelist
		_exports_DOMNodeList_objectDefinition.hasProperty = JSCNodeListHasPropertyCallback;
		_exports_DOMNodeList_objectDefinition.getProperty = JSCNodeListGetPropertyCallback;

		// not thread safe!
		{
			std::lock_guard<std::mutex> lock(_initMutex);
			JSCDOM_initialize(_ctx, &exports);
		}
#endif

		// introduce global functions as objects for private data
		JSClassRef jsInClassRef = JSClassCreate(&jsInClassDef);
		JSObjectRef jsIn = JSObjectMake(_ctx, jsInClassRef, this);
		JSStringRef inName = JSStringCreateWithUTF8CString("In");
		JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), inName, jsIn, kJSPropertyAttributeNone, NULL);
		JSStringRelease(inName);

		JSClassRef jsPrintClassRef = JSClassCreate(&jsPrintClassDef);
		JSObjectRef jsPrint = JSObjectMake(_ctx, jsPrintClassRef, this);
		JSStringRef printName = JSStringCreateWithUTF8CString("print");
		JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), printName, jsPrint, kJSPropertyAttributeNone, NULL);
		JSStringRelease(printName);

		JSClassRef jsInvokerClassRef = JSClassCreate(&jsInvokersClassDef);
		JSObjectRef jsInvoker = JSObjectMake(_ctx, jsInvokerClassRef, this);
		JSStringRef invokerName = JSStringCreateWithUTF8CString("_invokers");
		JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), invokerName, jsInvoker, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
		JSStringRelease(invokerName);

		JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef);
		JSObjectRef jsIOProc = JSObjectMake(_ctx, jsIOProcClassRef, this);
		JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors");
		JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), ioProcName, jsIOProc, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
		JSStringRelease(ioProcName);

		if (_callbacks) {
			JSStringRef nameName = JSStringCreateWithUTF8CString("_name");
			JSStringRef name = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(_callbacks->getName()).c_str());
			JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), nameName, JSValueMakeString(_ctx, name), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
			JSStringRelease(nameName);
			JSStringRelease(name);

			JSStringRef sessionIdName = JSStringCreateWithUTF8CString("_sessionid");
			JSStringRef sessionId = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(_callbacks->getSessionId()).c_str());
			JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), sessionIdName, JSValueMakeString(_ctx, sessionId), kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
			JSStringRelease(sessionIdName);
			JSStringRelease(sessionId);
		}

		evalAsValue("_x = {};");
	}

	void JSCDataModel::setEvent(const Event& event) {
		Event* evPtr = new Event(event);

		JSObjectRef eventObj = SWIG_JSC_NewPointerObj(_ctx, evPtr, SWIGTYPE_p_uscxml__Event, SWIG_POINTER_OWN);
		JSObjectRef globalObject = JSContextGetGlobalObject(_ctx);

		JSValueRef exception = NULL;

		/* Manually handle swig ignored fields */
		EVENT_STRING_OR_UNDEF(sendid, !event.hideSendId); // test333
		EVENT_STRING_OR_UNDEF(origin, event.origin.size() > 0); // test335
		EVENT_STRING_OR_UNDEF(origintype, event.origintype.size() > 0); // test337
		EVENT_STRING_OR_UNDEF(invokeid, event.invokeid.size() > 0); // test339

		/* Manually handle swig ignored event type */
		JSStringRef eventTypeName = JSStringCreateWithUTF8CString("type");
		JSStringRef eventTypeVal;

		// test 331
		const std::string sEventType = Event::TypeToString(event.eventType);
		if (!sEventType.empty())
			eventTypeVal = JSStringCreateWithUTF8CString(sEventType.c_str());

		JSObjectSetProperty(_ctx, eventObj, eventTypeName, JSValueMakeString(_ctx, eventTypeVal), 0, &exception);
		if (exception)
			handleException(exception, "event.eventType:[" + sEventType + "]");

		JSStringRelease(eventTypeName);
		JSStringRelease(eventTypeVal);

		/* Manually handle swig ignored event data */
		if (event.data.node) {
#ifndef NO_XERCESC
			JSStringRef propName = JSStringCreateWithUTF8CString("data");
			JSObjectSetProperty(_ctx, eventObj, propName, getNodeAsValue(event.data.node), 0, &exception);
			JSStringRelease(propName);
			if (exception)
				handleException(exception, "event.data.node:[" + event.data.asJSON() + "]");
#else
			ERROR_EXECUTION_THROW("Compiled without DOM support");
#endif
#if 0
		}
		else if (event.content.length() > 0) {
			// _event.data is a string or JSON
			Data json = Data::fromJSON(event.content);
			if (!json.empty()) {
				JSStringRef propName = JSStringCreateWithUTF8CString("data");
				JSObjectSetProperty(_ctx, eventObj, propName, getDataAsValue(json), 0, &exception);
				JSStringRelease(propName);
				if (exception)
					handleException(exception);
			}
			else {
				JSStringRef propName = JSStringCreateWithUTF8CString("data");
				JSStringRef contentStr = JSStringCreateWithUTF8CString(spaceNormalize(event.content).c_str());
				JSObjectSetProperty(_ctx, eventObj, propName, JSValueMakeString(_ctx, contentStr), 0, &exception);
				JSStringRelease(propName);
				JSStringRelease(contentStr);

				if (exception)
					handleException(exception);
			}
#endif
		}
		else {
			// _event.data is KVP
			Event eventCopy(event);
			if (!eventCopy.params.empty()) {
				Event::params_t::iterator paramIter = eventCopy.params.begin();
				while (paramIter != eventCopy.params.end()) {
					eventCopy.data.compound[paramIter->first] = paramIter->second;
					paramIter++;
				}
			}
			if (!eventCopy.namelist.empty()) {
				Event::namelist_t::iterator nameListIter = eventCopy.namelist.begin();
				while (nameListIter != eventCopy.namelist.end()) {
					eventCopy.data.compound[nameListIter->first] = nameListIter->second;
					nameListIter++;
				}
			}
			if (!eventCopy.data.empty()) {
				JSStringRef propName = JSStringCreateWithUTF8CString("data");
				JSObjectSetProperty(_ctx, eventObj, propName, getDataAsValue(eventCopy.data), 0, &exception);
				JSStringRelease(propName);
				if (exception)
					handleException(exception, "event.data:[" + eventCopy.data.asJSON() + "]");
			}
			else {
				// test 343 / test 488
				JSStringRef propName = JSStringCreateWithUTF8CString("data");
				JSObjectSetProperty(_ctx, eventObj, propName, JSValueMakeUndefined(_ctx), 0, &exception);
				JSStringRelease(propName);
				if (exception)
					handleException(exception, "event.data:[undefined]");
			}
		}
		JSStringRef eventName = JSStringCreateWithUTF8CString("_event");
		JSObjectSetProperty(_ctx, globalObject, eventName, eventObj, kJSPropertyAttributeDontDelete, &exception);
		JSStringRelease(eventName);
		if (exception)
			handleException(exception, "_event");

	}

	Data JSCDataModel::getAsData(const std::string& content) {
		Data d;
		try {
			/* SCXML-tutorial\Tests\ecma\Custom\types\testConditionalExpressions.scxml */
			d = evalAsData(content);
		}
		catch (uscxml::ErrorEvent &) {
			// parse as JSON test578
			d = Data::fromJSON(content);
			if (!d.empty()) {
				return d;
			}

			std::string trimmed = boost::trim_copy(content);
			if (trimmed.length() > 0) {
				if (isNumeric(trimmed.c_str(), 10)) {
					d = Data(trimmed, Data::INTERPRETED);
				}
				else if (trimmed.length() >= 2 &&
					((trimmed[0] == '"' && trimmed[trimmed.length() - 1] == '"') ||
					(trimmed[0] == '\'' && trimmed[trimmed.length() - 1] == '\''))) {
					d = Data(trimmed.substr(1, trimmed.length() - 2), Data::VERBATIM);
				}
				else {
					// test558, test562
					ERROR_EXECUTION(e, "Given content cannot be interpreted as data");
					e.data.compound["context"] = Data(trimmed, Data::VERBATIM);
					throw e;
				}
			}
		}
		return d;
	}

	JSValueRef JSCDataModel::getDataAsValue(const Data& data) {
		JSValueRef exception = NULL;

		if (data.node) {
#ifndef NO_XERCESC
			return getNodeAsValue(data.node);
#else
			ERROR_EXECUTION_THROW("Compiled without DOM support");
#endif

		}
		if (data.compound.size() > 0) {
			JSObjectRef value = JSObjectMake(_ctx, 0, 0);
			std::map<std::string, Data>::const_iterator compoundIter = data.compound.begin();
			while (compoundIter != data.compound.end()) {
				JSStringRef key = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(compoundIter->first).c_str());
				JSObjectSetProperty(_ctx, value, key, getDataAsValue(compoundIter->second), 0, &exception);
				JSStringRelease(key);
				if (exception)
					handleException(exception, "data.compound:[" + data.asJSON() + "]");
				compoundIter++;
			}
			return value;
		}
		if (data.array.size() > 0) {
			std::vector<JSValueRef> elements(data.array.size());
			int count = 0;
			for (const auto &arrayIter : data.array) {
				auto ref = getDataAsValue(arrayIter.second);
				elements[count++] = ref;
			}

			JSObjectRef value = JSObjectMakeArray(_ctx, data.array.size(), elements.data(), &exception);
			if (exception)
				handleException(exception, "data.array:[" + data.asJSON() + "]");
			return value;
		}
		if (data.atom.size() > 0) {
			switch (data.type) {
			case Data::VERBATIM: {
				JSStringRef stringRef = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(data.atom).c_str());
				JSValueRef value = JSValueMakeString(_ctx, stringRef);
				JSStringRelease(stringRef);
				return value;
				break;
			}
			case Data::INTERPRETED: {
				return evalAsValue(data.atom);
				break;
			}
			}
		}

		return JSValueMakeUndefined(_ctx);
	}

	Data JSCDataModel::getValueAsData(const JSValueRef value) {
		Data data;
		JSValueRef exception = NULL;
		switch (JSValueGetType(_ctx, value)) {
		case kJSTypeUndefined: {
			data.atom = "undefined";
			data.type = Data::INTERPRETED;
		} break;
		case kJSTypeNull: {
			data.atom = "null";
			data.type = Data::INTERPRETED;
		} break;
		case kJSTypeBoolean: {
			data.atom = (JSValueToBoolean(_ctx, value) ? "true" : "false");
		} break;
		case kJSTypeNumber: {
			data.atom = toStr(JSValueToNumber(_ctx, value, &exception));
			if (exception)
				handleException(exception);
		} break;
		case kJSTypeString: {
			JSStringRef stringValue = JSValueToStringCopy(_ctx, value, &exception);
			if (exception)
				handleException(exception);

			data.atom = JS2StringAndRelease(stringValue);
			data.type = Data::VERBATIM;
		} break;
		case kJSTypeObject: {
			JSObjectRef objValue = JSValueToObject(_ctx, value, &exception);
			if (exception)
				handleException(exception);

#ifndef NO_XERCESC
			if (JSValueIsObjectOfClass(_ctx, value, _exports_DOMNode_classRef)) {
				// dom node
				void* privData = NULL;
				SWIG_JSC_ConvertPtr(_ctx, value, &privData, SWIGTYPE_p_XERCES_CPP_NAMESPACE__DOMNode, 0);
				data.node = (XERCESC_NS::DOMNode*)privData;
				return data;
			}
#endif
			if (JSObjectIsFunction(_ctx, objValue)) {
				JSStringRef stringValue = JSValueToStringCopy(_ctx, value, &exception);
				if (exception)
					handleException(exception);

				data.atom = JS2StringAndRelease(stringValue);
				data.type = Data::INTERPRETED;
				return data;
			}

			std::set<std::string> propertySet;

			JSPropertyNameArrayRef properties = JSObjectCopyPropertyNames(_ctx, objValue);
			size_t paramCount = JSPropertyNameArrayGetCount(properties);
			bool isArray = true;
			for (size_t i = 0; i < paramCount; i++) {
				JSStringRef stringValue = JSPropertyNameArrayGetNameAtIndex(properties, i);
				const std::string property = JS2String(stringValue);
				if (!isInteger(property.c_str(), 10))
					isArray = false;
				propertySet.insert(property);
			}
			JSPropertyNameArrayRelease(properties);
			std::set<std::string>::iterator propIter = propertySet.begin();
			while (propIter != propertySet.end()) {
				if (isArray) {
					const int propIndex = strTo<int>(*propIter);
					JSValueRef nestedValue = JSObjectGetPropertyAtIndex(_ctx, objValue, propIndex, &exception);
					if (exception)
						handleException(exception);
					data.array.insert(std::make_pair(propIndex, getValueAsData(nestedValue)));
				}
				else {
					JSStringRef jsString = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(*propIter).c_str());
					JSValueRef nestedValue = JSObjectGetProperty(_ctx, objValue, jsString, &exception);
					JSStringRelease(jsString);
					if (exception)
						handleException(exception, "property:[" + *propIter + "]");
					data.compound[*propIter] = getValueAsData(nestedValue);
				}
				propIter++;
			}

			// consider that we have data as empty object '{}' or complex object like 'new Date()'
			if (data.empty()) {
				throw JSComplexClassException();
			}
		} break;
		}
		return data;
	}

	uint32_t JSCDataModel::getLength(const std::string& expr) {
		JSValueRef result;

		result = evalAsValue("(" + expr + ").length");
		JSType type = JSValueGetType(_ctx, result);
		if (type == kJSTypeNull || type == kJSTypeUndefined) {
			ERROR_EXECUTION_THROW("'" + expr + "' does not evaluate to an array.");
		}

		JSValueRef exception = NULL;
		double length = JSValueToNumber(_ctx, result, &exception);
		if (exception)
			handleException(exception, "getLength:[" + expr + "]");

		return (uint32_t)length;
	}

	void JSCDataModel::setForeach(const std::string& item,
		const std::string& array,
		const std::string& index,
		uint32_t iteration) {
		if (!isDeclared(item)) {
			assign(item, Data("null", Data::INTERPRETED));
		}
		// assign array element to item
		std::stringstream ss;
		ss << array << "[" << iteration << "]";
		assign(item, Data(ss.str(), Data::INTERPRETED));
		if (index.length() > 0) {
			// assign iteration element to index
			std::stringstream ss;
			ss << iteration;
			assign(index, Data(ss.str(), Data::INTERPRETED));
		}
	}

	bool JSCDataModel::isValidExprSyntax(const std::string& expr) {
		return isValidScriptSyntax("var __tmp=" + boost::trim_copy(expr) + ";");
	}

	bool JSCDataModel::isValidScriptSyntax(const std::string & script)
	{
		JSStringRef scriptJS = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(script).c_str());
		JSValueRef exception = NULL;
		bool valid = JSCheckScriptSyntax(_ctx, scriptJS, NULL, 0, &exception);
		JSStringRelease(scriptJS);

		if (exception) {
			if (_callbacks) {
				try {
					handleException(exception, script);
				}
				catch (uscxml::ErrorEvent &e) {
					LOG(_callbacks->getLogger(), USCXML_ERROR) << e << std::endl;
				}
			}
			else {
				/* option to use for external syntax check */
				handleException(exception, script);
			}
			return false;
		}

		if (!valid)
			return false;

		return true;
	}

	bool JSCDataModel::isDeclared(const std::string& expr) {
		JSStringRef scriptJS = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(expr).c_str());
		JSValueRef exception = NULL;
		JSValueRef result = JSEvaluateScript(_ctx, scriptJS, NULL, NULL, 0, &exception);
		JSStringRelease(scriptJS);

		if (exception || JSValueIsNull(_ctx, result)) {
			return false;
		}
		return true;
	}

	bool JSCDataModel::evalAsBool(const std::string& expr) {
		JSValueRef result = evalAsValue(expr);
		return JSValueToBoolean(_ctx, result);
	}

	void JSCDataModel::eval(const std::string & content) {
		evalAsValue(content);
	}

	Data JSCDataModel::evalAsData(const std::string& content) {
		try {
			if (!content.empty()) {
				try {
					JSValueRef result = evalAsValue("var __tmp=function() { return(" + content + "); }; __tmp();");

					return getValueAsData(result);
				}
				catch (JSComplexClassException &) {
					return Data(content, Data::INTERPRETED);
				}
			}
		}
		catch (ErrorEvent e) {
			// test453 vs test554
			throw e;
		}
		return Data("undefined", Data::INTERPRETED);
	}

	JSValueRef JSCDataModel::evalAsValue(const std::string& expr, bool dontThrow) {
		// test326
		if (expr.empty())
			return JSValueMakeUndefined(_ctx);

		JSStringRef scriptJS = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(expr).c_str());
		JSValueRef exception = NULL;
		JSValueRef result = JSEvaluateScript(_ctx, scriptJS, NULL, NULL, 0, &exception);
		JSStringRelease(scriptJS);

		if (exception && !dontThrow)
			handleException(exception, expr);

		return result;
	}

#ifndef NO_XERCESC
	JSValueRef JSCDataModel::getNodeAsValue(const DOMNode* node) {
		return SWIG_JSC_NewPointerObj(_ctx,
			(void*)node,
			SWIG_TypeDynamicCast(SWIGTYPE_p_XERCES_CPP_NAMESPACE__DOMNode,
				SWIG_as_voidptrptr(&node)),
			0);

	}
#endif

	void JSCDataModel::assign(const std::string& location, const Data& data, const std::map<std::string, std::string>& attr) {

		// flags on attribute are ignored?
		if (location.compare("_sessionid") == 0) // test 322
			ERROR_EXECUTION_THROW("Cannot assign to _sessionId");
		if (location.compare("_name") == 0)
			ERROR_EXECUTION_THROW("Cannot assign to _name");
		if (location.compare("_ioprocessors") == 0)  // test 326
			ERROR_EXECUTION_THROW("Cannot assign to _ioprocessors");
		if (location.compare("_invokers") == 0)
			ERROR_EXECUTION_THROW("Cannot assign to _invokers");
		if (location.compare("_event") == 0)
			ERROR_EXECUTION_THROW("Cannot assign to _event");

		JSValueRef exception = NULL;
		if (data.node) {
#ifndef NO_XERCESC
			JSObjectSetProperty(_ctx, JSContextGetGlobalObject(_ctx), JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(location).c_str()), getNodeAsValue(data.node), 0, &exception);
#else
			ERROR_EXECUTION_THROW("Compiled without DOM support");
#endif
		}
		else {

			if (data.type == Data::VERBATIM && !data.atom.empty() && isValidExprSyntax(data.atom)) {
				evalAsValue(location + "=" + data.atom);
			}
			else {
				evalAsValue(location + "=" + Data::toJSON(data));
			}
		}

		if (exception)
			handleException(exception, "location:[" + location + "] data:[" + data.asJSON() + "]");
	}

	void JSCDataModel::init(const std::string& location, const Data& data, const std::map<std::string, std::string>& attr) {
		try {
			if (data.empty()) {
				assign(location, Data("null", Data::INTERPRETED));
			}
			else {
				assign(location, data);
			}
		}
		catch (ErrorEvent e) {
			// test 277
			evalAsValue(location + " = undefined", true);
			throw e;
		}
	}

	void JSCDataModel::handleException(JSValueRef exception, const std::string &description /*=""*/) {

		std::string sLine = "";

		JSValueRef eObj = nullptr;
		JSObjectRef objRef = JSValueToObject(_ctx, exception, &eObj);
		if (!eObj && objRef) {
#if 0 // deep debug
			DumpJSObject(_callbacks->getLogger(), _ctx, objRef);
#endif
			JSValueRef eProp = nullptr;
			JSStringRef jsPropName = JSStringCreateWithUTF8CString("line");
			JSValueRef jsPropValue = JSObjectGetProperty(_ctx, objRef, jsPropName, &eProp);
			JSStringRelease(jsPropName);
			if (!eProp && jsPropValue) {
				sLine = JS2StringAndRelease(JSValueToStringCopy(_ctx, jsPropValue, NULL)) + ":";
			}
		}

		uscxml::ErrorEvent e;
		e.data.compound["cause"] = uscxml::Data(sLine + JS2StringAndRelease(JSValueToStringCopy(_ctx, exception, NULL)), uscxml::Data::VERBATIM);
		e.name = "error.execution";
		e.eventType = uscxml::Event::PLATFORM;

		if (_callbacks && !_callbacks->getName().empty()) {
			e.data.compound["interpreter"] = Data(_callbacks->getName(), Data::VERBATIM);
		}
		if (!description.empty()) {
			e.data.compound["description"] = Data(description, Data::VERBATIM);
		}
		throw e;
	}

	JSValueRef JSCDataModel::jsPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(function);

		for (unsigned int i = 0; i < argumentCount; i++) {
			if (JSValueIsString(ctx, arguments[i])) {
				JSStringRef stringRef = JSValueToStringCopy(ctx, arguments[i], exception);
				if (*exception)
					INSTANCE->handleException(*exception, "jsPrint arg:" + std::to_string(i));

				INSTANCE->_callbacks->getLogger().log(USCXML_LOG) << JS2StringAndRelease(stringRef);
			}
		}
		return JSValueMakeUndefined(ctx);
	}

	JSValueRef JSCDataModel::jsIn(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(function);

		for (unsigned int i = 0; i < argumentCount; i++) {
			if (JSValueIsString(ctx, arguments[i])) {
				JSStringRef stringRef = JSValueToStringCopy(ctx, arguments[i], exception);
				if (*exception)
					INSTANCE->handleException(*exception);

				if (INSTANCE->_callbacks->isInState(JS2StringAndRelease(stringRef))) {
					continue;
				}
			}
			return JSValueMakeBoolean(ctx, false);
		}
		return JSValueMakeBoolean(ctx, true);

	}

	bool JSCDataModel::jsIOProcessorHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
		std::map<std::string, IOProcessor> ioProcessors = INSTANCE->_callbacks->getIOProcessors();

		const std::string prop = JS2String(propertyName);

		return ioProcessors.find(prop) != ioProcessors.end();
	}

	JSValueRef JSCDataModel::jsIOProcessorGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
		std::map<std::string, IOProcessor> ioProcessors = INSTANCE->_callbacks->getIOProcessors();

		const std::string prop = JS2String(propertyName);

		auto it = ioProcessors.find(prop);
		if (it != ioProcessors.end()) {
			return INSTANCE->getDataAsValue(it->second.getDataModelVariables());
		}
		return JSValueMakeUndefined(ctx);
	}

	void JSCDataModel::jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
		std::map<std::string, IOProcessor> ioProcessors = INSTANCE->_callbacks->getIOProcessors();

		std::map<std::string, IOProcessor>::const_iterator ioProcIter = ioProcessors.begin();
		while (ioProcIter != ioProcessors.end()) {
			JSStringRef ioProcName = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(ioProcIter->first).c_str());
			JSPropertyNameAccumulatorAddName(propertyNames, ioProcName);
			ioProcIter++;
		}
	}

	bool JSCDataModel::jsInvokerHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
		std::map<std::string, Invoker> invokers = INSTANCE->_callbacks->getInvokers();

		const std::string prop = JS2String(propertyName);

		return invokers.find(prop) != invokers.end();
	}

	JSValueRef JSCDataModel::jsInvokerGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
		std::map<std::string, Invoker> invokers = INSTANCE->_callbacks->getInvokers();

		const std::string prop = JS2String(propertyName);

		if (invokers.find(prop) != invokers.end()) {
			return INSTANCE->getDataAsValue(invokers.find(prop)->second.getDataModelVariables());
		}
		return JSValueMakeUndefined(ctx);
	}

	void JSCDataModel::jsInvokerListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
		JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
		std::map<std::string, Invoker> invokers = INSTANCE->_callbacks->getInvokers();

		std::map<std::string, Invoker>::const_iterator invokerIter = invokers.begin();
		while (invokerIter != invokers.end()) {
			JSStringRef invokeName = JSStringCreateWithUTF8CString(uscxml::fromLocaleToUtf8(invokerIter->first).c_str());
			JSPropertyNameAccumulatorAddName(propertyNames, invokeName);
			JSStringRelease(invokeName);
			invokerIter++;
		}
	}

}


text:
#include <vector>
#include <string>

// Executes for a long time.
std::vector<std::string> read_defaults();

namespace first_attempt {

struct postprocessor {
    typedef std::vector<std::string> answer_t;

    // Concurrent calls on the same variable are safe.
    answer_t act(const std::string& in) const {
        if (in.empty()) {
            // Extremely rare condition.
            return read_defaults();
        }

        // ...
        answer_t ret;
        return ret;
    }
};

} // namespace first_attempt

namespace second_attempt {

struct postprocessor {
    typedef std::vector<std::string> answer_t;

private:
    answer_t default_;

public:
    postprocessor()
        : default_(read_defaults())
    {}

    // Concurrent calls on the same variable are safe.
    answer_t act(const std::string& in) const {
        if (in.empty()) {
            // Extremely rare condition.
            return default_;
        }

        // ...
        answer_t ret;
        return ret;
    }
};

} // namespace second_attempt

#include <boost/thread/once.hpp>

namespace right_solution {

struct postprocessor {
    typedef std::vector<std::string> answer_t;

private:
    mutable boost::once_flag    default_flag_;
    mutable answer_t            default_;

public:
    postprocessor()
        : default_flag_(BOOST_ONCE_INIT)
        , default_()
    {}

    // Concurrent calls on the same variable are safe.
    answer_t act(const std::string& in) const {
        answer_t ret;
        if (in.empty()) {
            // Extremely rare condition.
            boost::call_once(default_flag_, [this]() {
                this->default_ = read_defaults();
            });
            return default_;
        }

        // ...
        return ret;
    }
};

} // namespace right_solution

#include <iostream>
void once_printer(int i) {
    static boost::once_flag flag = BOOST_ONCE_INIT;
    boost::call_once(
        flag,
        [](int v) { std::cout << "Print once " << v << '\n'; },
        i // <=== Passed to lambda from above.
    );

    // ...
}

#include <cassert>
int main() {
    right_solution::postprocessor pp;
    assert(pp.act(std::string()).size() == 5);
    assert(pp.act("Hello").size() == 0);

    for (unsigned i = 0; i < 10; ++i) {
        once_printer(i);
    }
}

// Details:

std::vector<std::string> read_defaults() {
    std::vector<std::string> ret  {
        "Do", "not", "look", "at", "me"
    };
    return ret;
}

max_stars_repo_name: apolukhin/boost-cookbook

max_issues_repo_name: apolukhin/boost-cookbook

max_forks_repo_name: apolukhin/boost-cookbook


text:
/**
 * This file defines the `IncrementableIterator` concept.
 */

#ifndef DUCK_INCREMENTABLE_ITERATOR_HPP
#define DUCK_INCREMENTABLE_ITERATOR_HPP

#include <duck/assignable.hpp>
#include <duck/copy_constructible.hpp>
#include <duck/detail/test_expression.hpp>
// makes it available to all the other iterator concepts
#include <duck/detail/iterator_concepts_ordering.hpp>

#include <boost/mpl/and.hpp>
#include <boost/type_traits/add_lvalue_reference.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/declval.hpp>

namespace duck {

/**
 * Metafunction returning whether an `Iterator` models the
 * `IncrementableIterator` concept.
 */
template <typename Iterator>
class is_incrementable_iterator {
    DUCK_I_TEST_EXPRESSION(pre_increment, ++boost::declval<I&>(), typename I);
    DUCK_I_TEST_EXPRESSION(post_increment, boost::declval<I&>()++, typename I);

public:
    typedef typename boost::mpl::and_<
                is_assignable<Iterator>,
                is_copy_constructible<Iterator>,

                boost::is_convertible<
                    typename pre_increment<Iterator>::type,
                    typename boost::add_lvalue_reference<Iterator>::type
                >,

                boost::is_convertible<
                    typename post_increment<Iterator>::type,
                    typename boost::remove_reference<Iterator>::type
                >
            >::type type;
    static bool const value = type::value;
};

//! `IncrementableIterator` concept.
struct IncrementableIterator {
    template <typename Iterator>
    struct apply
        : is_incrementable_iterator<Iterator>
    { };
};

} // end namespace duck

#endif // !DUCK_INCREMENTABLE_ITERATOR_HPP

max_stars_repo_name: ldionne/duck

max_issues_repo_name: ldionne/duck

max_forks_repo_name: ldionne/duck


text:
#include <cmath>
#include <functional>
#include <iostream>

#include <Eigen/Dense>

#include <franka/duration.h>
#include <franka/exception.h>
#include <franka/model.h>
#include <franka/robot.h>

#include <plug_in_controller.h>

namespace plug_in_controller {

void run(const std::string& robot_ip,
         const Parameters plug_in_params,
         const double duration,  // in seconds
         const std::array<double, 3> target_position_array,
         const std::array<double, 3> target_tolerance_array) {
  // Parameters for stopping criterion
  Eigen::Vector3d target_position(Eigen::Vector3d::Map(target_position_array.data()));
  Eigen::Vector3d target_tolerance(Eigen::Vector3d::Map(target_tolerance_array.data()));

  // Compliance parameters
  Eigen::MatrixXd cartesian_stiffness(6, 6), cartesian_damping(6, 6);
  cartesian_stiffness.setZero();
  cartesian_stiffness.topLeftCorner(3, 3)
      << plug_in_params.translational_stiffness * Eigen::MatrixXd::Identity(3, 3);
  cartesian_stiffness.bottomRightCorner(3, 3)
      << plug_in_params.rotational_stiffness * Eigen::MatrixXd::Identity(3, 3);
  cartesian_damping.setZero();
  cartesian_damping.topLeftCorner(3, 3)
      << 2.0 * sqrt(plug_in_params.translational_stiffness) * Eigen::MatrixXd::Identity(3, 3);
  cartesian_damping.bottomRightCorner(3, 3)
      << 2.0 * sqrt(plug_in_params.rotational_stiffness) * Eigen::MatrixXd::Identity(3, 3);

  // Force parameters
  Eigen::VectorXd force_error_integral(6);
  // force control P, I gain
  double k_p{0.0};
  double k_i{1.0};

  franka::Robot robot(robot_ip);
  // load the kinematics and dynamics model
  franka::Model model = robot.loadModel();

  // initial robot state
  franka::RobotState initial_state = robot.readOnce();
  Eigen::Map<Eigen::Matrix<double, 6, 1>> force_initial(initial_state.O_F_ext_hat_K.data());
  force_error_integral.setZero();

  // equilibrium point is the initial position
  Eigen::Affine3d initial_transform(Eigen::Matrix4d::Map(initial_state.O_T_EE.data()));
  Eigen::Vector3d position_d(initial_transform.translation());
  Eigen::Quaterniond orientation_initial(initial_transform.linear());

  double time = 0.0;

  // define callback for the torque control loop
  std::function<franka::Torques(const franka::RobotState&, franka::Duration)>
      plug_in_control_callback =
          [&](const franka::RobotState& robot_state, franka::Duration period) -> franka::Torques {
    time += period.toSec();

    // get state variables
    std::array<double, 7> coriolis_array = model.coriolis(robot_state);
    std::array<double, 42> jacobian_array =
        model.zeroJacobian(franka::Frame::kEndEffector, robot_state);

    // convert to Eigen
    Eigen::Map<const Eigen::Matrix<double, 7, 1>> coriolis(coriolis_array.data());
    Eigen::Map<const Eigen::Matrix<double, 6, 7>> jacobian(jacobian_array.data());
    Eigen::Map<const Eigen::Matrix<double, 6, 1>> force(robot_state.O_F_ext_hat_K.data());
    Eigen::Map<const Eigen::Matrix<double, 7, 1>> dq(robot_state.dq.data());
    Eigen::Affine3d transform(Eigen::Matrix4d::Map(robot_state.O_T_EE.data()));
    Eigen::Vector3d position(transform.translation());
    Eigen::Quaterniond orientation(transform.linear());

    // Compute desired orientation of equilibrium pose and desired forces
    // wiggle motion
    Eigen::AngleAxisd angle_axis_wiggle_x;
    angle_axis_wiggle_x.axis() << 1, 0, 0;
    angle_axis_wiggle_x.angle() = sin(2.0 * M_PI * time * plug_in_params.wiggle_frequency_x) *
                                  plug_in_params.wiggle_amplitude_x;
    Eigen::AngleAxisd angle_axis_wiggle_y;
    angle_axis_wiggle_y.axis() << 0, 1, 0;
    angle_axis_wiggle_y.angle() = sin(2.0 * M_PI * time * plug_in_params.wiggle_frequency_y) *
                                  plug_in_params.wiggle_amplitude_y;
    Eigen::Quaterniond wiggle_x(angle_axis_wiggle_x);
    Eigen::Quaterniond wiggle_y(angle_axis_wiggle_y);
    Eigen::Quaterniond orientation_d(wiggle_y * (wiggle_x * orientation_initial));

    // desired forces
    Eigen::VectorXd desired_force(6);
    desired_force.setZero();
    desired_force(2) = -plug_in_params.desired_force;

    // Compute error to desired equilibrium pose
    // position error
    Eigen::Matrix<double, 6, 1> error;
    error.head(3) << position - position_d;

    // orientation error
    if (orientation_d.coeffs().dot(orientation.coeffs()) < 0.0) {
      orientation.coeffs() << -orientation.coeffs();
    }
    // "difference" quaternion
    Eigen::Quaterniond error_quaternion(orientation.inverse() * orientation_d);
    error.tail(3) << error_quaternion.x(), error_quaternion.y(), error_quaternion.z();
    // Transform to base frame
    error.tail(3) << -transform.linear() * error.tail(3);

    // Compute error to desired force removing initial bias
    Eigen::VectorXd force_error;
    force_error = desired_force - force + force_initial;
    force_error_integral = force_error_integral + period.toSec() * force_error;

    // Compute control
    Eigen::VectorXd force_control(6), tau_force(7), tau_cart(7), tau_cmd(7);

    // Force control term
    force_control = desired_force + k_p * force_error + k_i * force_error_integral;
    force_control << 0, 0, force_control(2), 0, 0, 0;
    tau_force = jacobian.transpose() * force_control;

    // Cartesian control term
    tau_cart << jacobian.transpose() *
                    (-cartesian_stiffness * error - cartesian_damping * (jacobian * dq));

    // Commanded torque
    tau_cmd << tau_cart + tau_force + coriolis;

    std::array<double, 7> tau_d_array{};
    Eigen::VectorXd::Map(&tau_d_array[0], 7) = tau_cmd;

    // check if motion is completed
    Eigen::Matrix<double, 3, 1> target_error((target_position - position).cwiseAbs());
    bool is_inserted =
        (target_error[0] <= target_tolerance[0] && target_error[1] <= target_tolerance[1] &&
         target_error[2] <= target_tolerance[2]);
    if (time <= duration && is_inserted) {
      return franka::MotionFinished(franka::Torques(tau_d_array));
    }
    if (time > duration) {
      throw franka::Exception("Timeout: Plug in controller failed!");
    }
    return tau_d_array;
  };

  robot.control(plug_in_control_callback);
}

}  // namespace plug_in_controller