<commit_before>#ifndef ECL_MAP
#define ECL_MAP

#include <utility>
#include <type_traits>
#include <array>
#include <initializer_list>

#include <ecl/tree/red_black_tree.hpp>

namespace ecl
{

template<typename K, typename V, std::size_t N, typename Compare = std::less<K>>
class map
{
    using tree_t                    = tree::red_black_tree
                                      <
                                            K
                                          , V
                                          , std::less
                                          , bool
                                      >;
    using tree_node_t               = typename tree_t::node_t;
    using tree_node_pointer_t       = typename std::add_pointer
                                               <
                                                   tree_node_t
                                               >::type;
    using const_tree_node_pointer_t = typename std::add_pointer
                                               <
                                                   typename std::add_const
                                                   <
                                                       tree_node_t
                                                   >::type
                                               >::type;
    using tree_node_reference_t     = typename std::add_lvalue_reference
                                               <
                                                   tree_node_t
                                               >::type;
public:
    using key_type                = typename tree_t::key_type;
    using mapped_type             = typename tree_t::value_type;
    using value_type              = std::pair<key_type, mapped_type>;
    using size_type               = std::size_t;
    using key_compare             = Compare;
    using value_compare           = std::less<value_type>;

    using reference               = typename std::add_lvalue_reference
                                             <
                                                 value_type
                                             >::type;
    using pointer                 = typename std::add_pointer<value_type>::type;
    using const_pointer           = typename std::add_pointer
                                             <
                                                 const value_type
                                             >::type;

    using iterator                = typename tree_t::iterator;
    using reverse_iterator        = typename tree_t::reverse_iterator;

    using const_iterator          = typename tree_t::const_iterator;
    using const_reverse_iterator  = typename tree_t::const_reverse_iterator;

    map()                                                               noexcept
        : m_nodes_pool()
    {
        init();
    }

    template<typename... Args>
    explicit map (Args&&... args)                                       noexcept
        : m_nodes_pool { { std::forward<Args>(args)... } }
    {
        static_assert(std::is_nothrow_default_constructible<mapped_type>::value,
            "Mapped type should be nothrow default constructible.");

        init();

        for(auto& n : m_nodes_pool)
        {
            insert({ n.key, n.val });
        }
    }

    map(std::initializer_list<value_type> ilist)                        noexcept
        : m_nodes_pool()
    {
        init();

        for(auto& e : ilist)
        {
            insert(e);
        }
    }

    // map& operator=(const map& other)                                    noexcept
    // map& operator=(map&& other)                                         noexcept;
    map& operator=(std::initializer_list<value_type> ilist)             noexcept;

    mapped_type& at(const key_type& key)                                noexcept
    {
        auto it = search(key);

        if(end() == it)
        {
            return not_found();
        }

        return it->second;
    }

    const mapped_type& at(const key_type& key)                    const noexcept
    {
        auto it = search(key);

        if(end() == it)
        {
            return not_found();
        }

        return it->second;
    }

    bool empty()                                                  const noexcept
    {
        return (0 == size());
    }

    size_type size()                                              const noexcept
    {
        return m_tree.count();
    }

    size_type max_size()                                          const noexcept
    {
        return N;
    }

    void clear()                                                        noexcept
    {
        for(auto& n : m_nodes_pool)
        {
            m_tree.erase(n.key);
            mark_as_unused(n);
        }
    }

    std::pair<iterator, bool> insert(const value_type& value)           noexcept
    {
        return insert_internal(value, false);
    }

    template<class P>
    std::pair<iterator, bool> insert(P&& value)                         noexcept
    {
        return insert_internal(value, false);
    }

    template< class InputIt >
    void insert( InputIt first, InputIt last )                          noexcept
    {
        while(first != last)
        {
            insert(first++);
        }
    }

    void insert( std::initializer_list<value_type> ilist )              noexcept
    {
        for(auto& e : ilist)
        {
            insert(e);
        }
    }

    iterator erase( const_iterator pos )                                noexcept
    {
        if(end() == pos)
        {
            return end();
        }

        iterator next = std::next(pos);

        auto ret = m_tree.erase(pos->first);

        if(nullptr == ret.first)
        {
            return end();
        }

        mark_as_unused(*(ret.first));

        return next;
    }

    iterator erase( const_iterator first, const_iterator last )         noexcept
    {
        while(first != last)
        {
            erase(first++);
        }

        return first;
    }

    size_type erase( const key_type& key )                              noexcept
    {
        auto ret = m_tree.erase(key);

        if(nullptr == ret.first)
        {
            return 0;
        }

        mark_as_unused(*ret.first);

        return 1;
    }

    void swap( map& other )                                             noexcept
    {
        std::swap ( m_tree       , other.m_tree       );
        std::swap ( m_nodes_pool , other.m_nodes_pool );
        std::swap ( m_not_found  , other.m_not_found  );
    }

    size_type count( const key_type& key )                        const noexcept
    {
        return (search(key) != end()) ? 1 : 0;
    }

    iterator find( const key_type& key )                                noexcept
    {
        return search(key);
    }

    const_iterator find( const key_type& key )                    const noexcept
    {
        return search(key);
    }

    std::pair<iterator,iterator> equal_range( const key_type& key )     noexcept;
    std::pair<const_iterator,const_iterator>
    equal_range(const key_type& key )                             const noexcept;
    iterator lower_bound( const key_type& key )                         noexcept;
    const_iterator lower_bound( const key_type& key )             const noexcept;
    iterator upper_bound( const key_type& key )                         noexcept;
    const_iterator upper_bound( const key_type& key )             const noexcept;

    key_compare key_comp()                                        const noexcept
    {
        return key_compare();
    }

    value_compare value_comp()                                    const noexcept
    {
        return value_compare();
    }

    mapped_type& operator[](const key_type& k)                          noexcept
    {
        iterator i = search(k);

        if(i == end())
        {
            iterator it = insert_internal({ k, mapped_type() }, true).first;
            return it->second;
        }

        return i->second;
    }

    const mapped_type& operator[](const key_type& k)              const noexcept
    {
        const_iterator i = search(k);

        if(i == end())
        {
            return not_found();
        }

        return i->second;
    }

    mapped_type& operator[](key_type&& k)                               noexcept
    {
        iterator i = search(std::forward<key_type>(k));

        if(i == end())
        {
            iterator it = insert_internal({ k, mapped_type() }, true).first;
            return it->second;
        }

        return i->second;
    }

    const mapped_type& operator[](key_type&& k)                   const noexcept
    {
        const_iterator i = search(std::forward<key_type>(k));

        if(i == end())
        {
            return not_found();
        }

        return i->second;
    }

    iterator begin()                                                    noexcept
    {
        return m_tree.begin();
    }

    iterator end()                                                      noexcept
    {
        return m_tree.end();
    }

    reverse_iterator rbegin()                                           noexcept
    {
        return m_tree.rbegin();
    }

    reverse_iterator rend()                                             noexcept
    {
        return m_tree.rend();
    }

    const_iterator begin()                                        const noexcept
    {
        return m_tree.begin();
    }

    const_iterator cbegin()                                       const noexcept
    {
        return m_tree.cbegin();
    }

    const_iterator end()                                          const noexcept
    {
        return m_tree.end();
    }

    const_iterator cend()                                         const noexcept
    {
        return m_tree.cend();
    }

    const_reverse_iterator rbegin()                               const noexcept
    {
        return m_tree.rbegin();
    }

    const_reverse_iterator crbegin()                              const noexcept
    {
        return m_tree.crbegin();
    }

    const_reverse_iterator rend()                                 const noexcept
    {
        return m_tree.rend();
    }

    const_reverse_iterator crend()                                const noexcept
    {
        return m_tree.crend();
    }

private:
    std::pair<iterator, bool> insert_internal(const value_type& value,
                                              bool allow_update)        noexcept
    {
        tree_node_pointer_t ptr = get_free_node();

        if(nullptr == ptr)
        {
            return { end(), false };
        }

        ptr->key = value.first;
        ptr->val = value.second;

        iterator i = m_tree.insert(ptr, allow_update);

        if(i != ptr)
        {
            return { i, false };
        }

        mark_as_used(*ptr);

        return { i, true };
    }

    void init()                                                         noexcept
    {
        for(auto& n : m_nodes_pool)
        {
            mark_as_unused(n);
        }
    }

    mapped_type& not_found()                                            noexcept
    {
        m_not_found = mapped_type();
        return m_not_found;
    }

    const mapped_type& not_found()                                const noexcept
    {
        return m_not_found;
    }

    bool is_node_free(const tree_node_reference_t n)              const noexcept
    {
        return !n._s.x;
    }

    void mark_as_used(tree_node_reference_t n)                          noexcept
    {
        n._s.x = true;
    }

    void mark_as_unused(tree_node_reference_t n)                        noexcept
    {
        n._s.x = false;
    }

    tree_node_pointer_t get_free_node()                                 noexcept
    {
        for(std::size_t i = 0; i < N; ++i)
        {
            if(is_node_free(m_nodes_pool[i]))
            {
                return &m_nodes_pool[i];
            }
        }

        return nullptr;
    }

    iterator search(key_type&& k)                                       noexcept
    {
        return m_tree.find(std::forward<key_type>(k));
    }

    iterator search(const key_type& k)                                  noexcept
    {
        return m_tree.find(k);
    }

    const_iterator search(key_type&& k)                           const noexcept
    {
        return m_tree.find(std::forward<key_type>(k));
    }

    const_iterator search(const key_type& k)                      const noexcept
    {
        return m_tree.find(k);
    }

    tree_t                     m_tree       {};
    std::array<tree_node_t, N> m_nodes_pool {};

    mapped_type                m_not_found  {};
};

template
<
      typename K
    , typename V
    , typename... Args
    , typename Compare = std::less<K>
>
constexpr inline const map
                       <
                             K
                           , V
                           , sizeof...(Args)
                           , Compare
                       > create_map(Args&&... args)                     noexcept
{
    static_assert(std::is_nothrow_default_constructible<V>::value,
        "Value type should be nothrow default constructible.");

    return map
           <
                 K
               , V
               , sizeof...(Args)
               , Compare
           >(std::forward<Args>(args)...);
}

} // namespace ecl

#endif // ECL_MAP
<commit_msg>Fix map comparator template parameter.<commit_after>#ifndef ECL_MAP
#define ECL_MAP

#include <utility>
#include <type_traits>
#include <array>
#include <initializer_list>

#include <ecl/tree/red_black_tree.hpp>

namespace ecl
{

template<typename K, typename V, std::size_t N, template<typename> class Compare = std::less>
class map
{
    using tree_t                    = tree::red_black_tree
                                      <
                                            K
                                          , V
                                          , Compare
                                          , bool
                                      >;
    using tree_node_t               = typename tree_t::node_t;
    using tree_node_pointer_t       = typename std::add_pointer
                                               <
                                                   tree_node_t
                                               >::type;
    using const_tree_node_pointer_t = typename std::add_pointer
                                               <
                                                   typename std::add_const
                                                   <
                                                       tree_node_t
                                                   >::type
                                               >::type;
    using tree_node_reference_t     = typename std::add_lvalue_reference
                                               <
                                                   tree_node_t
                                               >::type;
public:
    using key_type                = typename tree_t::key_type;
    using mapped_type             = typename tree_t::value_type;
    using value_type              = std::pair<key_type, mapped_type>;
    using size_type               = std::size_t;
    using key_compare             = Compare<K>;
    using value_compare           = std::less<value_type>;

    using reference               = typename std::add_lvalue_reference
                                             <
                                                 value_type
                                             >::type;
    using pointer                 = typename std::add_pointer<value_type>::type;
    using const_pointer           = typename std::add_pointer
                                             <
                                                 const value_type
                                             >::type;

    using iterator                = typename tree_t::iterator;
    using reverse_iterator        = typename tree_t::reverse_iterator;

    using const_iterator          = typename tree_t::const_iterator;
    using const_reverse_iterator  = typename tree_t::const_reverse_iterator;

    map()                                                               noexcept
        : m_nodes_pool()
    {
        init();
    }

    template<typename... Args>
    explicit map (Args&&... args)                                       noexcept
        : m_nodes_pool { { std::forward<Args>(args)... } }
    {
        static_assert(std::is_nothrow_default_constructible<mapped_type>::value,
            "Mapped type should be nothrow default constructible.");

        init();

        for(auto& n : m_nodes_pool)
        {
            insert({ n.key, n.val });
        }
    }

    map(std::initializer_list<value_type> ilist)                        noexcept
        : m_nodes_pool()
    {
        init();

        for(auto& e : ilist)
        {
            insert(e);
        }
    }

    // map& operator=(const map& other)                                    noexcept
    // map& operator=(map&& other)                                         noexcept;
    map& operator=(std::initializer_list<value_type> ilist)             noexcept;

    mapped_type& at(const key_type& key)                                noexcept
    {
        auto it = search(key);

        if(end() == it)
        {
            return not_found();
        }

        return it->second;
    }

    const mapped_type& at(const key_type& key)                    const noexcept
    {
        auto it = search(key);

        if(end() == it)
        {
            return not_found();
        }

        return it->second;
    }

    bool empty()                                                  const noexcept
    {
        return (0 == size());
    }

    size_type size()                                              const noexcept
    {
        return m_tree.count();
    }

    size_type max_size()                                          const noexcept
    {
        return N;
    }

    void clear()                                                        noexcept
    {
        for(auto& n : m_nodes_pool)
        {
            m_tree.erase(n.key);
            mark_as_unused(n);
        }
    }

    std::pair<iterator, bool> insert(const value_type& value)           noexcept
    {
        return insert_internal(value, false);
    }

    template<class P>
    std::pair<iterator, bool> insert(P&& value)                         noexcept
    {
        return insert_internal(value, false);
    }

    template< class InputIt >
    void insert( InputIt first, InputIt last )                          noexcept
    {
        while(first != last)
        {
            insert(first++);
        }
    }

    void insert( std::initializer_list<value_type> ilist )              noexcept
    {
        for(auto& e : ilist)
        {
            insert(e);
        }
    }

    iterator erase( const_iterator pos )                                noexcept
    {
        if(end() == pos)
        {
            return end();
        }

        iterator next = std::next(pos);

        auto ret = m_tree.erase(pos->first);

        if(nullptr == ret.first)
        {
            return end();
        }

        mark_as_unused(*(ret.first));

        return next;
    }

    iterator erase( const_iterator first, const_iterator last )         noexcept
    {
        while(first != last)
        {
            erase(first++);
        }

        return first;
    }

    size_type erase( const key_type& key )                              noexcept
    {
        auto ret = m_tree.erase(key);

        if(nullptr == ret.first)
        {
            return 0;
        }

        mark_as_unused(*ret.first);

        return 1;
    }

    void swap( map& other )                                             noexcept
    {
        std::swap ( m_tree       , other.m_tree       );
        std::swap ( m_nodes_pool , other.m_nodes_pool );
        std::swap ( m_not_found  , other.m_not_found  );
    }

    size_type count( const key_type& key )                        const noexcept
    {
        return (search(key) != end()) ? 1 : 0;
    }

    iterator find( const key_type& key )                                noexcept
    {
        return search(key);
    }

    const_iterator find( const key_type& key )                    const noexcept
    {
        return search(key);
    }

    std::pair<iterator,iterator> equal_range( const key_type& key )     noexcept;
    std::pair<const_iterator,const_iterator>
    equal_range(const key_type& key )                             const noexcept;
    iterator lower_bound( const key_type& key )                         noexcept;
    const_iterator lower_bound( const key_type& key )             const noexcept;
    iterator upper_bound( const key_type& key )                         noexcept;
    const_iterator upper_bound( const key_type& key )             const noexcept;

    key_compare key_comp()                                        const noexcept
    {
        return key_compare();
    }

    value_compare value_comp()                                    const noexcept
    {
        return value_compare();
    }

    mapped_type& operator[](const key_type& k)                          noexcept
    {
        iterator i = search(k);

        if(i == end())
        {
            iterator it = insert_internal({ k, mapped_type() }, true).first;
            return it->second;
        }

        return i->second;
    }

    const mapped_type& operator[](const key_type& k)              const noexcept
    {
        const_iterator i = search(k);

        if(i == end())
        {
            return not_found();
        }

        return i->second;
    }

    mapped_type& operator[](key_type&& k)                               noexcept
    {
        iterator i = search(std::forward<key_type>(k));

        if(i == end())
        {
            iterator it = insert_internal({ k, mapped_type() }, true).first;
            return it->second;
        }

        return i->second;
    }

    const mapped_type& operator[](key_type&& k)                   const noexcept
    {
        const_iterator i = search(std::forward<key_type>(k));

        if(i == end())
        {
            return not_found();
        }

        return i->second;
    }

    iterator begin()                                                    noexcept
    {
        return m_tree.begin();
    }

    iterator end()                                                      noexcept
    {
        return m_tree.end();
    }

    reverse_iterator rbegin()                                           noexcept
    {
        return m_tree.rbegin();
    }

    reverse_iterator rend()                                             noexcept
    {
        return m_tree.rend();
    }

    const_iterator begin()                                        const noexcept
    {
        return m_tree.begin();
    }

    const_iterator cbegin()                                       const noexcept
    {
        return m_tree.cbegin();
    }

    const_iterator end()                                          const noexcept
    {
        return m_tree.end();
    }

    const_iterator cend()                                         const noexcept
    {
        return m_tree.cend();
    }

    const_reverse_iterator rbegin()                               const noexcept
    {
        return m_tree.rbegin();
    }

    const_reverse_iterator crbegin()                              const noexcept
    {
        return m_tree.crbegin();
    }

    const_reverse_iterator rend()                                 const noexcept
    {
        return m_tree.rend();
    }

    const_reverse_iterator crend()                                const noexcept
    {
        return m_tree.crend();
    }

private:
    std::pair<iterator, bool> insert_internal(const value_type& value,
                                              bool allow_update)        noexcept
    {
        tree_node_pointer_t ptr = get_free_node();

        if(nullptr == ptr)
        {
            return { end(), false };
        }

        ptr->key = value.first;
        ptr->val = value.second;

        iterator i = m_tree.insert(ptr, allow_update);

        if(i != ptr)
        {
            return { i, false };
        }

        mark_as_used(*ptr);

        return { i, true };
    }

    void init()                                                         noexcept
    {
        for(auto& n : m_nodes_pool)
        {
            mark_as_unused(n);
        }
    }

    mapped_type& not_found()                                            noexcept
    {
        m_not_found = mapped_type();
        return m_not_found;
    }

    const mapped_type& not_found()                                const noexcept
    {
        return m_not_found;
    }

    bool is_node_free(const tree_node_reference_t n)              const noexcept
    {
        return !n._s.x;
    }

    void mark_as_used(tree_node_reference_t n)                          noexcept
    {
        n._s.x = true;
    }

    void mark_as_unused(tree_node_reference_t n)                        noexcept
    {
        n._s.x = false;
    }

    tree_node_pointer_t get_free_node()                                 noexcept
    {
        for(std::size_t i = 0; i < N; ++i)
        {
            if(is_node_free(m_nodes_pool[i]))
            {
                return &m_nodes_pool[i];
            }
        }

        return nullptr;
    }

    iterator search(key_type&& k)                                       noexcept
    {
        return m_tree.find(std::forward<key_type>(k));
    }

    iterator search(const key_type& k)                                  noexcept
    {
        return m_tree.find(k);
    }

    const_iterator search(key_type&& k)                           const noexcept
    {
        return m_tree.find(std::forward<key_type>(k));
    }

    const_iterator search(const key_type& k)                      const noexcept
    {
        return m_tree.find(k);
    }

    tree_t                     m_tree       {};
    std::array<tree_node_t, N> m_nodes_pool {};

    mapped_type                m_not_found  {};
};

template
<
      typename K
    , typename V
    , typename... Args
    , template<typename> class Compare = std::less
>
constexpr inline const map
                       <
                             K
                           , V
                           , sizeof...(Args)
                           , Compare
                       > create_map(Args&&... args)                     noexcept
{
    static_assert(std::is_nothrow_default_constructible<V>::value,
        "Value type should be nothrow default constructible.");

    return map
           <
                 K
               , V
               , sizeof...(Args)
               , Compare
           >(std::forward<Args>(args)...);
}

} // namespace ecl

#endif // ECL_MAP
<|endoftext|>


<commit_before>// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// 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)

#include "stdafx.h"
#include <ctype.h>
#include "request_parser.h"
#include "request.h"
#include <boost/lexical_cast.hpp>

namespace Http {

request_parser::request_parser()
    :
    content_length_(0),
    state_(method_start),
    content_consumed_(0)
{
}

void request_parser::reset()
{
    state_ = method_start;
    content_consumed_ = 0;
}

std::string request_parser::content_length_name_ = "Content-Length";
const std::string content_type_name = "Content-Type";

boost::tribool request_parser::consume(Request& req, char input)
{
    switch (state_)
    {
    case method_start:
        req.method.clear();
        req.uri.clear();
        req.http_version_major = 0;
        req.http_version_minor = 0;
        req.headers.clear();
        req.content.clear();
        content_length_ = 0;

        if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            state_ = method;
            req.method.push_back(input);
            return boost::indeterminate;
        }
    case method:
        if (input == ' ') {
            state_ = uri;
            return boost::indeterminate;
        } else if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            req.method.push_back(input);
            return boost::indeterminate;
        }
    case uri_start:
        if ( is_ctl(input) ) {
            return false;
        } else {
            state_ = uri;
            req.uri.push_back(input);
            return boost::indeterminate;
        }
    case uri:
        if (input == ' ') {
            state_ = http_version_h;
            return boost::indeterminate;
        } else if ( is_ctl(input) ) {
            return false;
        } else {
            req.uri.push_back(input);
            return boost::indeterminate;
        }
    case http_version_h:
        if (input == 'H') {
            state_ = http_version_t_1;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_t_1:
        if (input == 'T') {
            state_ = http_version_t_2;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_t_2:
        if (input == 'T') {
            state_ = http_version_p;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_p:
        if (input == 'P') {
            state_ = http_version_slash;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_slash:
        if (input == '/') {
            req.http_version_major = 0;
            req.http_version_minor = 0;
            state_ = http_version_major_start;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_major_start:
        if ( is_digit(input) ) {
            req.http_version_major = req.http_version_major * 10 + input - '0';
            state_ = http_version_major;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_major:
        if (input == '.') {
            state_ = http_version_minor_start;
            return boost::indeterminate;
        } else if ( is_digit(input) ) {
            req.http_version_major = req.http_version_major * 10 + input - '0';
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_minor_start:
        if ( is_digit(input) ) {
            req.http_version_minor = req.http_version_minor * 10 + input - '0';
            state_ = http_version_minor;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_minor:
        if (input == '\r') {
            state_ = expecting_newline_1;
            return boost::indeterminate;
        } else if ( is_digit(input) ) {
            req.http_version_minor = req.http_version_minor * 10 + input - '0';
            return boost::indeterminate;
        } else {
            return false;
        }
    case expecting_newline_1:
        if (input == '\n') {
            state_ = header_line_start;
            return boost::indeterminate;
        } else {
            return false;
        }
    case header_line_start:
        if (input == '\r') {
            state_ = expecting_newline_3;
            return boost::indeterminate;
        } else if ( !req.headers.empty() && (input == ' ' || input == '\t') ) {
            state_ = header_lws;
            return boost::indeterminate;
        } else if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            req.headers.push_back(header());
            req.headers.back().name.push_back(input);
            state_ = header_name;
            return boost::indeterminate;
        }
    case header_lws:
        if (input == '\r') {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        } else if (input == ' ' || input == '\t') {
            return boost::indeterminate;
        } else if ( is_ctl(input) ) {
            return false;
        } else {
            state_ = header_value;
            req.headers.back().value.push_back(input);
            return boost::indeterminate;
        }
    case header_name:
        if (input == ':') {
            state_ = space_before_header_value;
            return boost::indeterminate;
        } else if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            req.headers.back().name.push_back(input);
            return boost::indeterminate;
        }
    case space_before_header_value:
        if (input == ' ') {
            state_ = header_value;
            return boost::indeterminate;
        } else {
            return false;
        }
    case header_value:
        if (input == '\r') {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        } else if ( is_ctl(input) ) {
            return false;
        } else {
            req.headers.back().value.push_back(input);
            return boost::indeterminate;
        }
    case expecting_newline_2:
        if (input == '\n') {
            state_ = header_line_start;
            return boost::indeterminate;
        } else {
            return false;
        }
    case expecting_newline_3:
        if (input == '\n') {
            // Check for optional Content-Length header.
            for (std::size_t i = 0; i < req.headers.size(); ++i) {
                if ( headers_equal(req.headers[i].name, content_length_name_) ) {
                    try {
                        content_length_ = boost::lexical_cast<std::size_t>(req.headers[i].value);
                        state_ = select_content_parser;
                        return boost::indeterminate;
                    } catch (boost::bad_lexical_cast&) {
                        return false;
                    }
                }
            }
            return true; // no Content-Length header, stop parsing.
        } else {
            return false;
        }
    case select_content_parser: {
        state_ = content;

        const auto header_it = std::find_if(req.headers.begin(), req.headers.end(),
                                            [](const header& h) { return h.name == content_type_name; }
                                            );
        if (header_it != req.headers.end()) {
            if (boost::starts_with(header_it->value, "multipart/form-data;")) {
                req.mpfd_parser.SetUploadedFilesStorage(Request::mpfd_parser_t::StoreUploadedFilesInMemory);
                req.mpfd_parser.SetMaxCollectedDataLength(20*1024);
                req.mpfd_parser.SetContentType(header_it->value);
                state_ = content_multipart_formdata;
                return boost::indeterminate;
            }
        }
        return consume(req, input);
                                }
    case content:
        // Content.
        if (req.content.size() < content_length_) {
            req.content.push_back(input);
            if (req.content.size() == content_length_) {
                return true;  // all content has been consumed, stop parsing.
            }
            return boost::indeterminate;
        }
        return false;
    case content_multipart_formdata:
        assert(!"mpfd must not be processed by one char");
        return false;
    default:
        return false;
    }
}

bool request_parser::is_char(int c)
{
    return c >= 0 && c <= 127;
}

bool request_parser::is_ctl(int c)
{
    return (c >= 0 && c <= 31) || (c == 127);
}

bool request_parser::is_tspecial(int c)
{
    switch (c)
    {
    case '(': case ')': case '<': case '>': case '@':
    case ',': case ';': case ':': case '\\': case '"':
    case '/': case '[': case ']': case '?': case '=':
    case '{': case '}': case ' ': case '\t':
        return true;
    default:
        return false;
    }
}

bool request_parser::is_digit(int c)
{
    return c >= '0' && c <= '9';
}

bool request_parser::tolower_compare(char a, char b)
{
  return ::tolower(a) == ::tolower(b);
}

bool request_parser::headers_equal(const std::string& a, const std::string& b)
{
  if ( a.length() != b.length() ) {
    return false;
  }

  return std::equal(a.begin(), a.end(), b.begin(),
                    &request_parser::tolower_compare);
}

} // namespace Http
<commit_msg>use 75Mb maximum for unbounded form data.<commit_after>// Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// 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)

#include "stdafx.h"
#include <ctype.h>
#include "request_parser.h"
#include "request.h"
#include <boost/lexical_cast.hpp>

namespace Http {

request_parser::request_parser()
    :
    content_length_(0),
    state_(method_start),
    content_consumed_(0)
{
}

void request_parser::reset()
{
    state_ = method_start;
    content_consumed_ = 0;
}

std::string request_parser::content_length_name_ = "Content-Length";
const std::string content_type_name = "Content-Type";

boost::tribool request_parser::consume(Request& req, char input)
{
    switch (state_)
    {
    case method_start:
        req.method.clear();
        req.uri.clear();
        req.http_version_major = 0;
        req.http_version_minor = 0;
        req.headers.clear();
        req.content.clear();
        content_length_ = 0;

        if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            state_ = method;
            req.method.push_back(input);
            return boost::indeterminate;
        }
    case method:
        if (input == ' ') {
            state_ = uri;
            return boost::indeterminate;
        } else if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            req.method.push_back(input);
            return boost::indeterminate;
        }
    case uri_start:
        if ( is_ctl(input) ) {
            return false;
        } else {
            state_ = uri;
            req.uri.push_back(input);
            return boost::indeterminate;
        }
    case uri:
        if (input == ' ') {
            state_ = http_version_h;
            return boost::indeterminate;
        } else if ( is_ctl(input) ) {
            return false;
        } else {
            req.uri.push_back(input);
            return boost::indeterminate;
        }
    case http_version_h:
        if (input == 'H') {
            state_ = http_version_t_1;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_t_1:
        if (input == 'T') {
            state_ = http_version_t_2;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_t_2:
        if (input == 'T') {
            state_ = http_version_p;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_p:
        if (input == 'P') {
            state_ = http_version_slash;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_slash:
        if (input == '/') {
            req.http_version_major = 0;
            req.http_version_minor = 0;
            state_ = http_version_major_start;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_major_start:
        if ( is_digit(input) ) {
            req.http_version_major = req.http_version_major * 10 + input - '0';
            state_ = http_version_major;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_major:
        if (input == '.') {
            state_ = http_version_minor_start;
            return boost::indeterminate;
        } else if ( is_digit(input) ) {
            req.http_version_major = req.http_version_major * 10 + input - '0';
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_minor_start:
        if ( is_digit(input) ) {
            req.http_version_minor = req.http_version_minor * 10 + input - '0';
            state_ = http_version_minor;
            return boost::indeterminate;
        } else {
            return false;
        }
    case http_version_minor:
        if (input == '\r') {
            state_ = expecting_newline_1;
            return boost::indeterminate;
        } else if ( is_digit(input) ) {
            req.http_version_minor = req.http_version_minor * 10 + input - '0';
            return boost::indeterminate;
        } else {
            return false;
        }
    case expecting_newline_1:
        if (input == '\n') {
            state_ = header_line_start;
            return boost::indeterminate;
        } else {
            return false;
        }
    case header_line_start:
        if (input == '\r') {
            state_ = expecting_newline_3;
            return boost::indeterminate;
        } else if ( !req.headers.empty() && (input == ' ' || input == '\t') ) {
            state_ = header_lws;
            return boost::indeterminate;
        } else if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            req.headers.push_back(header());
            req.headers.back().name.push_back(input);
            state_ = header_name;
            return boost::indeterminate;
        }
    case header_lws:
        if (input == '\r') {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        } else if (input == ' ' || input == '\t') {
            return boost::indeterminate;
        } else if ( is_ctl(input) ) {
            return false;
        } else {
            state_ = header_value;
            req.headers.back().value.push_back(input);
            return boost::indeterminate;
        }
    case header_name:
        if (input == ':') {
            state_ = space_before_header_value;
            return boost::indeterminate;
        } else if ( !is_char(input) || is_ctl(input) || is_tspecial(input) ) {
            return false;
        } else {
            req.headers.back().name.push_back(input);
            return boost::indeterminate;
        }
    case space_before_header_value:
        if (input == ' ') {
            state_ = header_value;
            return boost::indeterminate;
        } else {
            return false;
        }
    case header_value:
        if (input == '\r') {
            state_ = expecting_newline_2;
            return boost::indeterminate;
        } else if ( is_ctl(input) ) {
            return false;
        } else {
            req.headers.back().value.push_back(input);
            return boost::indeterminate;
        }
    case expecting_newline_2:
        if (input == '\n') {
            state_ = header_line_start;
            return boost::indeterminate;
        } else {
            return false;
        }
    case expecting_newline_3:
        if (input == '\n') {
            // Check for optional Content-Length header.
            for (std::size_t i = 0; i < req.headers.size(); ++i) {
                if ( headers_equal(req.headers[i].name, content_length_name_) ) {
                    try {
                        content_length_ = boost::lexical_cast<std::size_t>(req.headers[i].value);
                        state_ = select_content_parser;
                        return boost::indeterminate;
                    } catch (boost::bad_lexical_cast&) {
                        return false;
                    }
                }
            }
            return true; // no Content-Length header, stop parsing.
        } else {
            return false;
        }
    case select_content_parser: {
        state_ = content;

        const auto header_it = std::find_if(req.headers.begin(), req.headers.end(),
                                            [](const header& h) { return h.name == content_type_name; }
                                            );
        if (header_it != req.headers.end()) {
            if (boost::starts_with(header_it->value, "multipart/form-data;")) {
                req.mpfd_parser.SetUploadedFilesStorage(Request::mpfd_parser_t::StoreUploadedFilesInMemory);
                req.mpfd_parser.SetMaxCollectedDataLength(75 * 1024 * 1024);
                req.mpfd_parser.SetContentType(header_it->value);
                state_ = content_multipart_formdata;
                return boost::indeterminate;
            }
        }
        return consume(req, input);
                                }
    case content:
        // Content.
        if (req.content.size() < content_length_) {
            req.content.push_back(input);
            if (req.content.size() == content_length_) {
                return true;  // all content has been consumed, stop parsing.
            }
            return boost::indeterminate;
        }
        return false;
    case content_multipart_formdata:
        assert(!"mpfd must not be processed by one char");
        return false;
    default:
        return false;
    }
}

bool request_parser::is_char(int c)
{
    return c >= 0 && c <= 127;
}

bool request_parser::is_ctl(int c)
{
    return (c >= 0 && c <= 31) || (c == 127);
}

bool request_parser::is_tspecial(int c)
{
    switch (c)
    {
    case '(': case ')': case '<': case '>': case '@':
    case ',': case ';': case ':': case '\\': case '"':
    case '/': case '[': case ']': case '?': case '=':
    case '{': case '}': case ' ': case '\t':
        return true;
    default:
        return false;
    }
}

bool request_parser::is_digit(int c)
{
    return c >= '0' && c <= '9';
}

bool request_parser::tolower_compare(char a, char b)
{
  return ::tolower(a) == ::tolower(b);
}

bool request_parser::headers_equal(const std::string& a, const std::string& b)
{
  if ( a.length() != b.length() ) {
    return false;
  }

  return std::equal(a.begin(), a.end(), b.begin(),
                    &request_parser::tolower_compare);
}

} // namespace Http
<|endoftext|>


<commit_before>#include "ofxGuiTabs.h"
#include "ofGraphics.h"
using namespace std;

ofxGuiTabs::ofxGuiTabs() :
	ofxGuiContainer(){

	setup();

}

ofxGuiTabs::ofxGuiTabs(const string &collectionName, const ofJson &config) :
	ofxGuiTabs(){

	setName(collectionName);
	_setConfig(config);

}

ofxGuiTabs::ofxGuiTabs(string collectionName, string filename, float x, float y)
	:ofxGuiTabs(collectionName){

	this->filename = filename;
	setPosition(x,y);

}

ofxGuiTabs::~ofxGuiTabs(){
	if(tabs){
		tabs->getActiveToggleIndex().removeListener(this, &ofxGuiTabs::_setActiveTab);
	}
	ofRemoveListener(childAdded, this, &ofxGuiTabs::onChildAdd);
}

void ofxGuiTabs::setup(){

	tabs = nullptr;
	pages.clear();
	activeToggle = nullptr;
	activePage = nullptr;

	setTheme();

	tabWidth.set("tab width", 100);
	tabHeight.set("tab height", 50);
	setConfig(ofJson({
		{"flex-direction", "column"},
		{"direction", "vertical"}
	 }));

	clear();

	ofAddListener(childAdded, this, &ofxGuiTabs::onChildAdd);

}

void ofxGuiTabs::clear(){

	if(tabs){
		tabs->getActiveToggleIndex().removeListener(this, &ofxGuiTabs::_setActiveTab);
	}

	ofxGuiContainer::clear();

	tabs = addContainer("tabs", ofJson({
		{"height", tabHeight.get()},
		{"align-items", "stretch"},
		{"justify-content", "flex-start"},
		{"margin", 0},
		{"border-width", 0},
		{"padding", "0 10"},
		{"flex-direction", "row"},
		{"direction", "horizontal"},
		{"background-color", "rgba(0,0,0,0)"}
	}));

	tabs->setExclusiveToggles(true);
	tabs->getActiveToggleIndex().addListener(this, &ofxGuiTabs::_setActiveTab);

}

void ofxGuiTabs::generateDraw(){

	for(unsigned int i = 0; i < pages.size(); i++){
		if(ofxGuiElement* page = dynamic_cast<ofxGuiElement*>(pages.at(i))){
			ofxGuiElement* tab = tabs->getControl(i);
			if(tab->getName() != page->getName()
					|| tab->getFillColor() != page->getBackgroundColor()){
				tab->setName(page->getName());
				tab->setFillColor(page->getBackgroundColor());
				tab->setBackgroundColor(ofColor(page->getBackgroundColor(), 120));
				tabs->updateLayout();
			}
		}
	}

	ofxGuiContainer::generateDraw();

	border.clear();
	bg.clear();
	if(activePage){
		int topy = activePage->getShape().getTop();
		border.moveTo(0, topy-borderWidth);
		bg.moveTo(borderWidth, topy);
		for(ofxGuiElement* tab : tabs->getControls()){
			border.lineTo(tab->getShape().getLeft()+tabs->getPosition().x-borderWidth, topy - borderWidth);
			border.lineTo(tab->getShape().getTopLeft()+tabs->getPosition() - ofPoint(borderWidth,borderWidth));
			border.lineTo(tab->getShape().getTopRight()+tabs->getPosition() + ofPoint(borderWidth, -borderWidth));
			border.lineTo(tab->getShape().getRight()+tabs->getPosition().x+borderWidth, topy - borderWidth);
			bg.lineTo(tab->getShape().getLeft()+tabs->getPosition().x, topy);
			bg.lineTo(tab->getShape().getTopLeft()+tabs->getPosition());
			bg.lineTo(tab->getShape().getTopRight()+tabs->getPosition());
			if(tab != activeToggle){
				bg.lineTo(tab->getShape().getRight()+tabs->getPosition().x, topy - borderWidth);
				bg.lineTo(tab->getShape().getLeft()+tabs->getPosition().x, topy - borderWidth);
				bg.lineTo(tab->getShape().getLeft()+tabs->getPosition().x, topy);
				bg.lineTo(tab->getShape().getRight()+tabs->getPosition().x, topy);
			}else{
				bg.lineTo(tab->getShape().getRight()+tabs->getPosition().x, topy);
			}
		}
		border.lineTo(getWidth(), topy - borderWidth);
		border.lineTo(getWidth(), getHeight());
		border.lineTo(0, getHeight());
		border.lineTo(0, topy-borderWidth);
		bg.lineTo(getWidth() - borderWidth, topy);
		bg.lineTo(getWidth() - borderWidth, getHeight() - borderWidth);
		bg.lineTo(borderWidth, getHeight() - borderWidth);
		bg.lineTo(borderWidth, topy);
	}
	border.append(bg);

}

void ofxGuiTabs::onChildAdd(DOM::ElementEventArgs &args){

	unsigned int nopages = 2;
	if(this->children().size() < nopages){
		return;
	}

	if(tabs){

		Element* _page = args.element();

		pages.push_back(_page);

		std::string name = "Page " + ofToString(pages.size());
		ofxGuiElement* page = dynamic_cast<ofxGuiElement*>(_page);
		if(page){
			name = page->getName();
			page->setHidden(true);
			page->setConfig(ofJson({
				{"position", "static"},
				{"flex", "auto"},
				{"align-self", "stretch"},
				{"margin", 0},
				{"show-header", false},
				{"border-width", 0}
			}));
		}

		ofJson toggleconfig = {
			{"width", tabWidth.get()},
			{"type", "fullsize"},
			{"margin", "0 20 0 0"},
			{"border-width", 0}
		};
		ofxGuiElement* tab = tabs->add<ofxGuiToggle>(name, toggleconfig);
		tab->setTextAlignment(TextAlignment::CENTERED);

		if(pages.size() == 1){
			setActiveTab(0);
		}

		invalidateChildShape();

	}

}

void ofxGuiTabs::setActiveTab(int index){
	_setActiveTab(index);
}

void ofxGuiTabs::_setActiveTab(int &index){
	tabs->setActiveToggle(index);
	for(auto &e : tabs->getControls()){
		e->setConfig(ofJson({{"margin-bottom", "1"}}));
	}
	activeToggle = tabs->getControl(index);
	activeToggle->setConfig(ofJson({{"margin-bottom", "-1"}}));
	for(auto &e : pages){
		e->setHidden(true);
	}
	pages.at(index)->setHidden(false);
	activePage = pages.at(index);
	invalidateChildShape();
}

ofParameter<int>& ofxGuiTabs::getActiveTabIndex(){
	return tabs->getActiveToggleIndex();
}

DOM::Element *ofxGuiTabs::getActiveTab(){
	return activePage;
}

void ofxGuiTabs::setTabHeight(int h){
	tabHeight = h;
	tabs->setHeight(h);
}

void ofxGuiTabs::setTabWidth(int w){
	tabWidth = w;
	for(auto & e: tabs->children()){
		e->setWidth(w);
	}
}

std::string ofxGuiTabs::getClassType(){
	return "tabs";
}

vector<std::string> ofxGuiTabs::getClassTypes(){
	vector<std::string> types = ofxGuiContainer::getClassTypes();
	types.push_back(getClassType());
	return types;
}
<commit_msg>make tabbar toggles not serializable, shoud fix #55<commit_after>#include "ofxGuiTabs.h"
#include "ofGraphics.h"
using namespace std;

ofxGuiTabs::ofxGuiTabs() :
	ofxGuiContainer(){

	setup();

}

ofxGuiTabs::ofxGuiTabs(const string &collectionName, const ofJson &config) :
	ofxGuiTabs(){

	setName(collectionName);
	_setConfig(config);

}

ofxGuiTabs::ofxGuiTabs(string collectionName, string filename, float x, float y)
	:ofxGuiTabs(collectionName){

	this->filename = filename;
	setPosition(x,y);

}

ofxGuiTabs::~ofxGuiTabs(){
	if(tabs){
		tabs->getActiveToggleIndex().removeListener(this, &ofxGuiTabs::_setActiveTab);
	}
	ofRemoveListener(childAdded, this, &ofxGuiTabs::onChildAdd);
}

void ofxGuiTabs::setup(){

	tabs = nullptr;
	pages.clear();
	activeToggle = nullptr;
	activePage = nullptr;

	setTheme();

	tabWidth.set("tab width", 100);
	tabHeight.set("tab height", 50);
	setConfig(ofJson({
		{"flex-direction", "column"},
		{"direction", "vertical"}
	 }));

	clear();

	ofAddListener(childAdded, this, &ofxGuiTabs::onChildAdd);

}

void ofxGuiTabs::clear(){

	if(tabs){
		tabs->getActiveToggleIndex().removeListener(this, &ofxGuiTabs::_setActiveTab);
	}

	ofxGuiContainer::clear();

	tabs = addContainer("tabs", ofJson({
		{"height", tabHeight.get()},
		{"align-items", "stretch"},
		{"justify-content", "flex-start"},
		{"margin", 0},
		{"border-width", 0},
		{"padding", "0 10"},
		{"flex-direction", "row"},
		{"direction", "horizontal"},
		{"background-color", "rgba(0,0,0,0)"}
	}));

	tabs->setExclusiveToggles(true);
	tabs->getActiveToggleIndex().addListener(this, &ofxGuiTabs::_setActiveTab);

}

void ofxGuiTabs::generateDraw(){

	for(unsigned int i = 0; i < pages.size(); i++){
		if(ofxGuiElement* page = dynamic_cast<ofxGuiElement*>(pages.at(i))){
			ofxGuiElement* tab = tabs->getControl(i);
			if(tab->getName() != page->getName()
					|| tab->getFillColor() != page->getBackgroundColor()){
				tab->setName(page->getName());
				tab->setFillColor(page->getBackgroundColor());
				tab->setBackgroundColor(ofColor(page->getBackgroundColor(), 120));
				tabs->updateLayout();
			}
		}
	}

	ofxGuiContainer::generateDraw();

	border.clear();
	bg.clear();
	if(activePage){
		int topy = activePage->getShape().getTop();
		border.moveTo(0, topy-borderWidth);
		bg.moveTo(borderWidth, topy);
		for(ofxGuiElement* tab : tabs->getControls()){
			border.lineTo(tab->getShape().getLeft()+tabs->getPosition().x-borderWidth, topy - borderWidth);
			border.lineTo(tab->getShape().getTopLeft()+tabs->getPosition() - ofPoint(borderWidth,borderWidth));
			border.lineTo(tab->getShape().getTopRight()+tabs->getPosition() + ofPoint(borderWidth, -borderWidth));
			border.lineTo(tab->getShape().getRight()+tabs->getPosition().x+borderWidth, topy - borderWidth);
			bg.lineTo(tab->getShape().getLeft()+tabs->getPosition().x, topy);
			bg.lineTo(tab->getShape().getTopLeft()+tabs->getPosition());
			bg.lineTo(tab->getShape().getTopRight()+tabs->getPosition());
			if(tab != activeToggle){
				bg.lineTo(tab->getShape().getRight()+tabs->getPosition().x, topy - borderWidth);
				bg.lineTo(tab->getShape().getLeft()+tabs->getPosition().x, topy - borderWidth);
				bg.lineTo(tab->getShape().getLeft()+tabs->getPosition().x, topy);
				bg.lineTo(tab->getShape().getRight()+tabs->getPosition().x, topy);
			}else{
				bg.lineTo(tab->getShape().getRight()+tabs->getPosition().x, topy);
			}
		}
		border.lineTo(getWidth(), topy - borderWidth);
		border.lineTo(getWidth(), getHeight());
		border.lineTo(0, getHeight());
		border.lineTo(0, topy-borderWidth);
		bg.lineTo(getWidth() - borderWidth, topy);
		bg.lineTo(getWidth() - borderWidth, getHeight() - borderWidth);
		bg.lineTo(borderWidth, getHeight() - borderWidth);
		bg.lineTo(borderWidth, topy);
	}
	border.append(bg);

}

void ofxGuiTabs::onChildAdd(DOM::ElementEventArgs &args){

	unsigned int nopages = 2;
	if(this->children().size() < nopages){
		return;
	}

	if(tabs){

		Element* _page = args.element();

		pages.push_back(_page);

		std::string name = "Page " + ofToString(pages.size());
		ofxGuiElement* page = dynamic_cast<ofxGuiElement*>(_page);
		if(page){
			name = page->getName();
			page->setHidden(true);
			page->setConfig(ofJson({
				{"position", "static"},
				{"flex", "auto"},
				{"align-self", "stretch"},
				{"margin", 0},
				{"show-header", false},
				{"border-width", 0}
			}));
		}

		ofJson toggleconfig = {
			{"width", tabWidth.get()},
			{"type", "fullsize"},
			{"margin", "0 20 0 0"},
			{"border-width", 0}
		};
		ofxGuiElement* tab = tabs->add<ofxGuiToggle>(name, toggleconfig);
		tab->getParameter().cast<ofParameter<bool>>().setSerializable(false);
		tab->setTextAlignment(TextAlignment::CENTERED);

		if(pages.size() == 1){
			setActiveTab(0);
		}

		invalidateChildShape();

	}

}

void ofxGuiTabs::setActiveTab(int index){
	_setActiveTab(index);
}

void ofxGuiTabs::_setActiveTab(int &index){
	tabs->setActiveToggle(index);
	for(auto &e : tabs->getControls()){
		e->setConfig(ofJson({{"margin-bottom", "1"}}));
	}
	activeToggle = tabs->getControl(index);
	activeToggle->setConfig(ofJson({{"margin-bottom", "-1"}}));
	for(auto &e : pages){
		e->setHidden(true);
	}
	pages.at(index)->setHidden(false);
	activePage = pages.at(index);
	invalidateChildShape();
}

ofParameter<int>& ofxGuiTabs::getActiveTabIndex(){
	return tabs->getActiveToggleIndex();
}

DOM::Element *ofxGuiTabs::getActiveTab(){
	return activePage;
}

void ofxGuiTabs::setTabHeight(int h){
	tabHeight = h;
	tabs->setHeight(h);
}

void ofxGuiTabs::setTabWidth(int w){
	tabWidth = w;
	for(auto & e: tabs->children()){
		e->setWidth(w);
	}
}

std::string ofxGuiTabs::getClassType(){
	return "tabs";
}

vector<std::string> ofxGuiTabs::getClassTypes(){
	vector<std::string> types = ofxGuiContainer::getClassTypes();
	types.push_back(getClassType());
	return types;
}
<|endoftext|>


<commit_before>#include "Controller.hpp"

Controller::Controller()
{

	//Subscriber
	//Subscriber for the MoveFormation data of the Quadcopters (1000 is the max. buffered messages)
	this->MoveFormation_sub = this->n.subscribe("MoveFormation", 1000, &Controller::MoveFormationCallback, this);
	//Subscriber for the SetFormation data of the Quadcopters (100 is the max. buffered messages)
	this->SetFormation_sub = this->n.subscribe("SetFormation", 100, &Controller::SetFormationCallback, this);
	//TODO multiple topics
	//Subscriber for the quadcopter status data of the Quadcopters (1000 is the max. buffered messages)
	//this->QuadStatus_sub = this->n.subscribe("quadcopter_status", 1000, &Controller::QuadStatusCallback, this);

	//Service
	//Service for BuildFormation and Shutdown
	this->BuildForm_srv  = this->n.advertiseService("BuildFormation", &Controller::buildFormation, this);
	this->Shutdown_srv = this->n.advertiseService("Shutdown", &Controller::shutdown, this);

	//Publisher
	//Publisher for the Movement data of the Quadcopts (1000 is the max. buffered messages)
	this->Movement_pub = this->n.advertise<control_application::quadcopter_movement>("quadcopter_movement", 1000);

	//Client
	this->FindAll_client = this->n.serviceClient<quadcopter_application::find_all>("find_all");
	this->Blink_client = this->n.serviceClient<quadcopter_application::blink>("blink");

	//Initializes invalid currentPosition and targetPosition
	double invalid[3] = {INVALID, INVALID, INVALID};
	this->currentPosition[0].setPosition(invalid);
	this->targetPosition[0].setPosition(invalid);
	//All control variables are set to zero
	this->shutdownStarted = 0;
}

void Controller::initialize()
{
	/*
	 * Start using threads here.
	 * tGet- One waiting to set new positions
	 * tCalc- One calculating the output
	 * tSend- One sending movement-data over ROS
	 *
	 * TODO: Could the following work?
	 * tGet is not a new thread, implemented as parent.
	 * Leave function and wait to be called by position-instance?
	 */

	/* TODO: Error-handling. */
	std:pthread_create(&tCalc, NULL, &calculateMovement, NULL);
	/* Unneccessary if move is not in loop */
	//std:pthread_create(&tSend, NULL, &move, NULL);

	shutdownMutex.lock();
	this->shutdownStarted = 0;
	shutdownMutex.unlock();

	//Initialization of quadcopters (find_all and create mapping + subscribe)
	quadcopter_application::find_all srv;
	//TODO initialization
	/*srv.request.seq = (unsigned int)0;
	srv.request.stamp = (time)0;
	srv.request.frame_id = "";*/
	std::string * uri;
	if(FindAll_client.call(srv))
	{
		uri = srv.response.uri;
		//this->totalAmount = srv.response.amount;

		//TODO Create map uri->id
		//Generate Subscribers
		for(int i = 0; i < this->totalAmount; i++)
		{
			std::stringstream topicName;
  			topicName << "quadcopter_status_" << i;
			this->QuadStatus_sub[i] = this->n.subscribe(topicName.str().c_str(), 1000, boost::bind(&Controller::QuadStatusCallback, _1, i));
		}
	}
}

void Controller::calculateMovement()
{

	/* TODO:  */

	/* As long as we are not in the shutdown process, calculate new Movement data */
	while(!shutdownStarted)
	{
		double moveVector[3];
		//Iterate over all the quadcopters and calculate the necessary movement.
		for(int i = 0; i < this->amount; i++)
		{
			//Gets the right hardware id/ String id
			//this->idString = this->quadcopters[i];
			this->id = i;
			tarPosMutex.lock();
			double * const target = this->targetPosition[i].getPosition();
			tarPosMutex.unlock();
			curPosMutex.lock();
			double * const current = this->currentPosition[i].getPosition();
			curPosMutex.unlock();
			moveVector[0] = target[0] - current[0];
			moveVector[1] = target[1] - current[1];
			moveVector[2] = target[2] - current[2];
			//Convert Movement vector to thurst, pitch... data
			convertMovement(moveVector);
			//Send Movement to the quadcopter
			sendMovement();
		}
	}
}
void Controller::sendMovement()
{
	//Creates a message for quadcopter Movement and sends it via Ros
	control_application::quadcopter_movement msg;
	msg.thrust = this->thrust;
	msg.yaw = this->yawrate;
	msg.pitch = this->pitch;
	msg.roll = this->roll;
	this->Movement_pub.publish(msg);
}

void Controller::convertMovement(double* vector)
{
	/* conversion from vectors to thrust, yawrate, pitch... */
	int thrust_react_z_low = -5;
	int thrust_react_z_high = 5;

	if (vector[2] > thrust_react_z_high) {
		this->thrust += THRUST_STEP;
	} else if (vector[2] < thrust_react_z_high) {
		this->thrust -= THRUST_STEP;
	} else {
		/* Not sure what to do here, maybe nothing. */
	}

	double length = 0;
	for (int i = 0; i < 3; i++) {
		length = length + vector[i]*vector[i];
	}
	length = sqrt(length);

	double ratio_roll = vector[0] / length;
	double ratio_pitch = vector[1] / length;

	this->roll = ratio_roll + ROLL_STEP;
	this->pitch = ratio_pitch + PITCH_STEP;

	this->yawrate = 0.0;
}

//Move the last Positions according to the formation movement vector (without orientation right now)
void Controller::setTargetPosition()
{
	//Iterate over all quadcopters in formation and set new target considering old target and formation Movement
	for(int i = 0; i < this->amount; i++)
	{
		tarPosMutex.lock();
		double * const targetOld = this->targetPosition[i].getPosition();
		tarPosMutex.unlock();
		double targetNew[3];
		targetNew[0] = targetOld[0] + this->formationMovement[0];
		targetNew[1] = targetOld[1] + this->formationMovement[1];
		targetNew[2] = targetOld[2] + this->formationMovement[2];
		this->targetPosition[i].setPosition(targetNew);
	}
}

/*
 * Builds Formation by starting one quadcopter after another, finding the right position and then
 * inclining a little to avoid collisions. So there is a being tracked and moving level, and a standing still
 * at the right position level.
 */
bool Controller::buildFormation(control_application::BuildFormation::Request  &req, control_application::BuildFormation::Response &res)
{
	//Get the formation Positions and the distance.
	Position6DOF* const formPos = this->formation.getPosition();
	double distance = this->formation.getDistance();
	//Pointer to the first tracked quadcopter
	double * first;
	//Start one quadcopter after another
	for(int i = 0; i < this->amount; i++)
	{
		//Starting/ Inclining process
		//this->idString = this->quadcopters[i];
		this->id = i;
		this->thrust = THRUST_START;
		this->yawrate = 0;
		this->pitch = 0;
		this->roll = 0;
		//Calculate the wanted position for quadcopter i
		double * pos = formPos[i].getPosition();
		double target[3];
		target[0] = pos[0] * distance;
		target[1] = pos[1] * distance;
		target[2] = pos[2] * distance;
		//Set target Position for quadcopter i
		this->targetPosition[i].setPosition(target);
		//As long as the quadcopter isn't tracked, incline
		while(!this->tracked[i])
		{
			sendMovement();
		}
		//If this is the first tracked quadcopter set it as a reference point for all the others
		if( i == 0)
		{
			curPosMutex.lock();
			first = this->currentPosition[0].getPosition();
			curPosMutex.unlock();
		}
		else
		{
			//Set all the other positions according to the first crazyflie
			target[0] += first[0];
			target[1] += first[1];
			target[2] += first[2];
			tarPosMutex.lock();
			this->targetPosition[i].setPosition(target);
			tarPosMutex.unlock();
			//Calculate Movement to the wanted position + convert it + send it
			calculateMovement();
		}
		//Incline a little bit to avoid collisions (there is a level with the qc which are already in position and a moving level)
		target[0] = 0;
		target[1] = distance;
		target[2] = 0;
		tarPosMutex.lock();
		this->targetPosition[i].setPosition(target);
		tarPosMutex.unlock();
		calculateMovement();
	}
	return true;
}

/*
 * Shutdown Formation
 * Set all values to zero and thrust to minimum. Send the values and do nothing
 * after that.
 * The thread for calculating the next values (target position, etc.) does not
 * exit.
 * TODO: Check description with actual code ...
 *
 */
void Controller::shutdownFormation()
{
	//Shutdown process is started
	this->shutdownStarted = 1;
	//Bring all quadcopters to a stand
	for(int i = 0; i < this->amount; i++)
	{
		//this->idString = this->quadcopters[i];
		this->id = i;
		this->thrust = THRUST_STAND_STILL;
		this->yawrate = 0;
		this->pitch = 0;
		this->roll = 0;
		this->shutdownStarted = 0;
		sendMovement();
	}
	//Decline each quadcopter till it's not tracked anymore and then shutdown motor
	for(int i = 0; i < this->amount; i++)
	{
		curPosMutex.lock();
		double * const current = this->currentPosition[id].getPosition();
		curPosMutex.unlock();
		//Decline until crazyflie isn't tracked anymore
		while(tracked[i] != INVALID)
		{
			this->thrust = THRUST_DECLINE;
			sendMovement();
		}
		//Shutdown crazyflie after having left the tracking area.
		this->thrust = THRUST_MIN;
		sendMovement();
	}
	//Shutdown process is finished
	this->shutdownStarted = 0;
}

/*
 * Shutdown
 * Set all values to zero and thrust to minimum. Send the values and exit program
 * after that.
 *
 */
bool Controller::shutdown(control_application::Shutdown::Request  &req, control_application::Shutdown::Response &res)
{
	shutdownFormation ();

	void *resultCalc;
	pthread_join(tCalc, &resultCalc);

	/* Unneccessary if move is not in loop */
	//void *resultSend;
	//pthread_join(tSend, &resultSend);
	return true;
}

/*
* Callback for Ros Subscriber of Formation Movement
*/
void Controller::MoveFormationCallback(const api_application::MoveFormation::ConstPtr &msg)
{
	ROS_INFO("I heard: %f", msg->xMovement);
	this->formationMovement[0] = msg->xMovement;
	this->formationMovement[1] = msg->yMovement;
	this->formationMovement[2] = msg->zMovement;
	//calculate and set a new target position each time there is new data
	setTargetPosition();
}

/*
* Callback for Ros Subscriber of set Formation
*/
void Controller::SetFormationCallback(const api_application::SetFormation::ConstPtr &msg)
{
	this->formation.setDistance(msg->distance);
	this->formation.setAmount(msg->amount);
	this->amount = msg->amount;
	//Iterate over all needed quadcopters for formation and set the formation position of each quadcopter
	Position6DOF formPos[this->amount];
	for(int i = 0; i < this->amount; i++)
	{
		double pos[3], ori[3];
		pos[0] = msg->xPositions[i];
		pos[1] = msg->yPositions[i];
		pos[2] = msg->zPositions[i];
		formPos[i].setPosition(pos);
		//Depends on the calculation of target and current position
		//ori[0] = msg->
		//ori[1] = msg->
		//ori[2] = msg->
		//formPos[i].setOrientation(ori);
	}
	this->formation.setPosition(formPos);
	//Initialize tracked (no quadcopter is tracked at the beginning)
	for(int i = 0; i < this->amount; i++)
	{
		this->tracked[i] = 0;
	}
}

/*
* Callback for Ros Subscriber of quadcopter status
*/
void Controller::QuadStatusCallback(const quadcopter_application::quadcopter_status::ConstPtr& msg, int topicNr)
{
	this->battery_status[topicNr] = msg->battery_status;
	this->roll_stab[topicNr] = msg->stabilizer_roll;
	this->pitch_stab[topicNr] = msg->stabilizer_pitch;
	this->yaw_stab[topicNr] = msg->stabilizer_yaw;
	this->thrust_stab[topicNr] = msg->stabilizer_thrust;
}
<commit_msg>Receive multiple topics. Compiles ;-)<commit_after>#include "Controller.hpp"

Controller::Controller()
{

	//Subscriber
	//Subscriber for the MoveFormation data of the Quadcopters (1000 is the max. buffered messages)
	this->MoveFormation_sub = this->n.subscribe("MoveFormation", 1000, &Controller::MoveFormationCallback, this);
	//Subscriber for the SetFormation data of the Quadcopters (100 is the max. buffered messages)
	this->SetFormation_sub = this->n.subscribe("SetFormation", 100, &Controller::SetFormationCallback, this);
	//TODO multiple topics
	//Subscriber for the quadcopter status data of the Quadcopters (1000 is the max. buffered messages)
	//this->QuadStatus_sub = this->n.subscribe("quadcopter_status", 1000, &Controller::QuadStatusCallback, this);

	//Service
	//Service for BuildFormation and Shutdown
	this->BuildForm_srv  = this->n.advertiseService("BuildFormation", &Controller::buildFormation, this);
	this->Shutdown_srv = this->n.advertiseService("Shutdown", &Controller::shutdown, this);

	//Publisher
	//Publisher for the Movement data of the Quadcopts (1000 is the max. buffered messages)
	this->Movement_pub = this->n.advertise<control_application::quadcopter_movement>("quadcopter_movement", 1000);

	//Client
	this->FindAll_client = this->n.serviceClient<quadcopter_application::find_all>("find_all");
	this->Blink_client = this->n.serviceClient<quadcopter_application::blink>("blink");

	//Initializes invalid currentPosition and targetPosition
	double invalid[3] = {INVALID, INVALID, INVALID};
	this->currentPosition[0].setPosition(invalid);
	this->targetPosition[0].setPosition(invalid);
	//All control variables are set to zero
	this->shutdownStarted = 0;
}

void Controller::initialize()
{
	/*
	 * Start using threads here.
	 * tGet- One waiting to set new positions
	 * tCalc- One calculating the output
	 * tSend- One sending movement-data over ROS
	 *
	 * TODO: Could the following work?
	 * tGet is not a new thread, implemented as parent.
	 * Leave function and wait to be called by position-instance?
	 */

	/* TODO: Error-handling. */
	std:pthread_create(&tCalc, NULL, &calculateMovement, NULL);
	/* Unneccessary if move is not in loop */
	//std:pthread_create(&tSend, NULL, &move, NULL);

	shutdownMutex.lock();
	this->shutdownStarted = 0;
	shutdownMutex.unlock();

	//Initialization of quadcopters (find_all and create mapping + subscribe)
	quadcopter_application::find_all srv;
	//TODO initialization
	/*srv.request.seq = (unsigned int)0;
	srv.request.stamp = (time)0;
	srv.request.frame_id = "";*/
	std::string * uri;
	if(FindAll_client.call(srv))
	{
		//TODO Get amount of quadcopter over api instead
		//uri = srv.response.uri;
		//this->totalAmount = srv.response.amount;

		//TODO Create map uri->id
		//Generate Subscribers
		for(int i = 0; i < this->totalAmount; i++)
		{
			std::stringstream topicName;
  			topicName << "quadcopter_status_" << i;
			this->QuadStatus_sub[i] = this->n.subscribe<quadcopter_application::quadcopter_status>(topicName.str().c_str(), 1000, boost::bind(&Controller::QuadStatusCallback, this, _1, i));

		}
	}
}

void Controller::calculateMovement()
{

	/* TODO:  */

	/* As long as we are not in the shutdown process, calculate new Movement data */
	while(!shutdownStarted)
	{
		double moveVector[3];
		//Iterate over all the quadcopters and calculate the necessary movement.
		for(int i = 0; i < this->amount; i++)
		{
			//Gets the right hardware id/ String id
			//this->idString = this->quadcopters[i];
			this->id = i;
			tarPosMutex.lock();
			double * const target = this->targetPosition[i].getPosition();
			tarPosMutex.unlock();
			curPosMutex.lock();
			double * const current = this->currentPosition[i].getPosition();
			curPosMutex.unlock();
			moveVector[0] = target[0] - current[0];
			moveVector[1] = target[1] - current[1];
			moveVector[2] = target[2] - current[2];
			//Convert Movement vector to thurst, pitch... data
			convertMovement(moveVector);
			//Send Movement to the quadcopter
			sendMovement();
		}
	}
}
void Controller::sendMovement()
{
	//Creates a message for quadcopter Movement and sends it via Ros
	control_application::quadcopter_movement msg;
	msg.thrust = this->thrust;
	msg.yaw = this->yawrate;
	msg.pitch = this->pitch;
	msg.roll = this->roll;
	this->Movement_pub.publish(msg);
}

void Controller::convertMovement(double* vector)
{
	/* conversion from vectors to thrust, yawrate, pitch... */
	int thrust_react_z_low = -5;
	int thrust_react_z_high = 5;

	if (vector[2] > thrust_react_z_high) {
		this->thrust += THRUST_STEP;
	} else if (vector[2] < thrust_react_z_high) {
		this->thrust -= THRUST_STEP;
	} else {
		/* Not sure what to do here, maybe nothing. */
	}

	double length = 0;
	for (int i = 0; i < 3; i++) {
		length = length + vector[i]*vector[i];
	}
	length = sqrt(length);

	double ratio_roll = vector[0] / length;
	double ratio_pitch = vector[1] / length;

	this->roll = ratio_roll + ROLL_STEP;
	this->pitch = ratio_pitch + PITCH_STEP;

	this->yawrate = 0.0;
}

//Move the last Positions according to the formation movement vector (without orientation right now)
void Controller::setTargetPosition()
{
	//Iterate over all quadcopters in formation and set new target considering old target and formation Movement
	for(int i = 0; i < this->amount; i++)
	{
		tarPosMutex.lock();
		double * const targetOld = this->targetPosition[i].getPosition();
		tarPosMutex.unlock();
		double targetNew[3];
		targetNew[0] = targetOld[0] + this->formationMovement[0];
		targetNew[1] = targetOld[1] + this->formationMovement[1];
		targetNew[2] = targetOld[2] + this->formationMovement[2];
		this->targetPosition[i].setPosition(targetNew);
	}
}

/*
 * Builds Formation by starting one quadcopter after another, finding the right position and then
 * inclining a little to avoid collisions. So there is a being tracked and moving level, and a standing still
 * at the right position level.
 */
bool Controller::buildFormation(control_application::BuildFormation::Request  &req, control_application::BuildFormation::Response &res)
{
	//Get the formation Positions and the distance.
	Position6DOF* const formPos = this->formation.getPosition();
	double distance = this->formation.getDistance();
	//Pointer to the first tracked quadcopter
	double * first;
	//Start one quadcopter after another
	for(int i = 0; i < this->amount; i++)
	{
		//Starting/ Inclining process
		//this->idString = this->quadcopters[i];
		this->id = i;
		this->thrust = THRUST_START;
		this->yawrate = 0;
		this->pitch = 0;
		this->roll = 0;
		//Calculate the wanted position for quadcopter i
		double * pos = formPos[i].getPosition();
		double target[3];
		target[0] = pos[0] * distance;
		target[1] = pos[1] * distance;
		target[2] = pos[2] * distance;
		//Set target Position for quadcopter i
		this->targetPosition[i].setPosition(target);
		//As long as the quadcopter isn't tracked, incline
		while(!this->tracked[i])
		{
			sendMovement();
		}
		//If this is the first tracked quadcopter set it as a reference point for all the others
		if( i == 0)
		{
			curPosMutex.lock();
			first = this->currentPosition[0].getPosition();
			curPosMutex.unlock();
		}
		else
		{
			//Set all the other positions according to the first crazyflie
			target[0] += first[0];
			target[1] += first[1];
			target[2] += first[2];
			tarPosMutex.lock();
			this->targetPosition[i].setPosition(target);
			tarPosMutex.unlock();
			//Calculate Movement to the wanted position + convert it + send it
			calculateMovement();
		}
		//Incline a little bit to avoid collisions (there is a level with the qc which are already in position and a moving level)
		target[0] = 0;
		target[1] = distance;
		target[2] = 0;
		tarPosMutex.lock();
		this->targetPosition[i].setPosition(target);
		tarPosMutex.unlock();
		calculateMovement();
	}
	return true;
}

/*
 * Shutdown Formation
 * Set all values to zero and thrust to minimum. Send the values and do nothing
 * after that.
 * The thread for calculating the next values (target position, etc.) does not
 * exit.
 * TODO: Check description with actual code ...
 *
 */
void Controller::shutdownFormation()
{
	//Shutdown process is started
	this->shutdownStarted = 1;
	//Bring all quadcopters to a stand
	for(int i = 0; i < this->amount; i++)
	{
		//this->idString = this->quadcopters[i];
		this->id = i;
		this->thrust = THRUST_STAND_STILL;
		this->yawrate = 0;
		this->pitch = 0;
		this->roll = 0;
		this->shutdownStarted = 0;
		sendMovement();
	}
	//Decline each quadcopter till it's not tracked anymore and then shutdown motor
	for(int i = 0; i < this->amount; i++)
	{
		curPosMutex.lock();
		double * const current = this->currentPosition[id].getPosition();
		curPosMutex.unlock();
		//Decline until crazyflie isn't tracked anymore
		while(tracked[i] != INVALID)
		{
			this->thrust = THRUST_DECLINE;
			sendMovement();
		}
		//Shutdown crazyflie after having left the tracking area.
		this->thrust = THRUST_MIN;
		sendMovement();
	}
	//Shutdown process is finished
	this->shutdownStarted = 0;
}

/*
 * Shutdown
 * Set all values to zero and thrust to minimum. Send the values and exit program
 * after that.
 *
 */
bool Controller::shutdown(control_application::Shutdown::Request  &req, control_application::Shutdown::Response &res)
{
	shutdownFormation ();

	void *resultCalc;
	pthread_join(tCalc, &resultCalc);

	/* Unneccessary if move is not in loop */
	//void *resultSend;
	//pthread_join(tSend, &resultSend);
	return true;
}

/*
* Callback for Ros Subscriber of Formation Movement
*/
void Controller::MoveFormationCallback(const api_application::MoveFormation::ConstPtr &msg)
{
	ROS_INFO("I heard: %f", msg->xMovement);
	this->formationMovement[0] = msg->xMovement;
	this->formationMovement[1] = msg->yMovement;
	this->formationMovement[2] = msg->zMovement;
	//calculate and set a new target position each time there is new data
	setTargetPosition();
}

/*
* Callback for Ros Subscriber of set Formation
*/
void Controller::SetFormationCallback(const api_application::SetFormation::ConstPtr &msg)
{
	this->formation.setDistance(msg->distance);
	this->formation.setAmount(msg->amount);
	this->amount = msg->amount;
	//Iterate over all needed quadcopters for formation and set the formation position of each quadcopter
	Position6DOF formPos[this->amount];
	for(int i = 0; i < this->amount; i++)
	{
		double pos[3], ori[3];
		pos[0] = msg->xPositions[i];
		pos[1] = msg->yPositions[i];
		pos[2] = msg->zPositions[i];
		formPos[i].setPosition(pos);
		//Depends on the calculation of target and current position
		//ori[0] = msg->
		//ori[1] = msg->
		//ori[2] = msg->
		//formPos[i].setOrientation(ori);
	}
	this->formation.setPosition(formPos);
	//Initialize tracked (no quadcopter is tracked at the beginning)
	for(int i = 0; i < this->amount; i++)
	{
		this->tracked[i] = 0;
	}
}

/*
* Callback for Ros Subscriber of quadcopter status
*/
void Controller::QuadStatusCallback(const quadcopter_application::quadcopter_status::ConstPtr& msg, int topicNr)
{
	this->battery_status[topicNr] = msg->battery_status;
	this->roll_stab[topicNr] = msg->stabilizer_roll;
	this->pitch_stab[topicNr] = msg->stabilizer_pitch;
	this->yaw_stab[topicNr] = msg->stabilizer_yaw;
	this->thrust_stab[topicNr] = msg->stabilizer_thrust;
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include "wrappers/sockets/client_socket.h"
#include "wrappers/sockets/server_socket.h"

// I decided to put all tests in one file, because I can only
// test them together, anyways.

TEST ( SocketsTest, GeneralTest )
{
    sockets::Server_socket server ( 12346 );
    // sockets::Client_socket client ( "127.0.0.1", 12346 );
    sockets::Client_socket client ( "localhost", 12346 );
    sockets::Client_socket accepted = server.next_socket ();

    std::string lines [] = { "This is the first line.", "This is the second one.", "And now there is a third one." };

    // Send from client to server
    for ( int i = 0; i < 3; i++ )
    {
        client.send ( lines [ i ] );
    }
    for ( int i = 0; i < 3; i++ )
    {
        EXPECT_EQ ( lines [ i ], accepted.read_line () );
    }

    // Send from server to client
    for ( int i = 0; i < 3; i++ )
    {
        accepted.send ( lines [ i ] );
    }
    for ( int i = 0; i < 3; i++ )
    {
        EXPECT_EQ ( lines [ i ], client.read_line () );
    }

    // Send an empty line
    client.send ( "" );

    // There should be a throw upon reading on a disconnected socket
    server.shutdown ();
    client.shutdown ();
    accepted.shutdown ();

    // The empty line shouldn't be read here
    EXPECT_THROW ( accepted.read_line (), std::runtime_error );

    // Connect to a ( hopefully ) noexistant host
    EXPECT_THROW ( sockets::Client_socket fail ( "adfkadsfjasjfdwefiasdfjvnasdf", 6445 ), std::runtime_error );
}
<commit_msg>Expand SocketsTest<commit_after>#include <gtest/gtest.h>

#include "wrappers/sockets/client_socket.h"
#include "wrappers/sockets/server_socket.h"

// I decided to put all tests in one file, because I can only
// test them together, anyways.

TEST ( SocketsTest, GeneralTest )
{
    sockets::Server_socket server ( 12346 );
    // sockets::Client_socket client ( "127.0.0.1", 12346 );
    sockets::Client_socket client ( "localhost", 12346 );
    sockets::Client_socket accepted = server.next_socket ();

    std::string lines [] = { "This is the first line.", "This is the second one.", "And now there is a third one." };

    // Send from client to server
    for ( int i = 0; i < 3; i++ )
    {
        client.send ( lines [ i ] );
    }
    for ( int i = 0; i < 3; i++ )
    {
        EXPECT_EQ ( lines [ i ], accepted.read_line () );
    }

    // Send from server to client
    for ( int i = 0; i < 3; i++ )
    {
        accepted.send ( lines [ i ] );
    }
    for ( int i = 0; i < 3; i++ )
    {
        EXPECT_EQ ( lines [ i ], client.read_line () );
    }

    // Send an empty line, which should be skipped
    client.send ( "" );
    // 520 characters, which exeed the buffer, but should still be read at once
    client.send ( "                                                                                " );
    EXPECT_EQ ( "                                                                                ", accepted.read_line () );

    // There should be a throw upon reading on a disconnected socket
    server.shutdown ();
    client.shutdown ();
    accepted.shutdown ();

    // The empty line shouldn't be read here
    EXPECT_THROW ( accepted.read_line (), std::runtime_error );

    // Connect to a ( hopefully ) noexistant host
    EXPECT_THROW ( sockets::Client_socket fail ( "adfkadsfjasjfdwefiasdfjvnasdf", 6445 ), std::runtime_error );
}
<|endoftext|>


<commit_before>/***************************************************
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED Matrix backpacks
  ----> http://www.adafruit.com/products/
  ----> http://www.adafruit.com/products/

  These displays use I2C to communicate, 2 pins are required to
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/
/*
#if (ARDUINO >= 100)
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#ifdef __AVR_ATtiny85__
 #include <TinyWireM.h>
#else
 #include <Wire.h>
#endif
*/
#include "Adafruit_GFX.h"

#define LED_ON 1
#define LED_OFF 0

#define LED_RED 1
#define LED_YELLOW 2
#define LED_GREEN 3

#define HT16K33_BLINK_CMD 0x80
#define HT16K33_BLINK_DISPLAYON 0x01
#define HT16K33_BLINK_OFF 0
#define HT16K33_BLINK_2HZ  1
#define HT16K33_BLINK_1HZ  2
#define HT16K33_BLINK_HALFHZ  3

#define HT16K33_CMD_BRIGHTNESS 0x0E

#define SEVENSEG_DIGITS 5

// this is the raw HT16K33 controller
class Adafruit_LEDBackpack {
 public:
  Adafruit_LEDBackpack(void);
  void begin(uint8_t _addr);
  void setBrightness(uint8_t b);
  void blinkRate(uint8_t b);
  void writeDisplay(void);
  void clear(void);

  uint16_t displaybuffer[8];

  void init(uint8_t a);
 private:
  uint8_t i2c_addr;
};

class Adafruit_24bargraph : public Adafruit_LEDBackpack {
 public:
  Adafruit_24bargraph(void);

  void setBar(uint8_t bar, uint8_t color);

 private:
};

class Adafruit_8x8matrix : public Adafruit_LEDBackpack, public Adafruit_GFX {
 public:
  Adafruit_8x8matrix(void);

  void drawPixel(int16_t x, int16_t y, uint16_t color);

 private:
};

class Adafruit_BicolorMatrix : public Adafruit_LEDBackpack, public Adafruit_GFX {
 public:
  Adafruit_BicolorMatrix(void);

  void drawPixel(int16_t x, int16_t y, uint16_t color);

 private:
};

#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0

class Adafruit_7segment : public Adafruit_LEDBackpack {
 public:
  Adafruit_7segment(void);
  size_t write(uint8_t c);

  void print(char, int = BYTE);
  void print(unsigned char, int = BYTE);
  void print(int, int = DEC);
  void print(unsigned int, int = DEC);
  void print(long, int = DEC);
  void print(unsigned long, int = DEC);
  void print(double, int = 2);
  void println(char, int = BYTE);
  void println(unsigned char, int = BYTE);
  void println(int, int = DEC);
  void println(unsigned int, int = DEC);
  void println(long, int = DEC);
  void println(unsigned long, int = DEC);
  void println(double, int = 2);
  void println(void);

  void writeDigitRaw(uint8_t x, uint8_t bitmask);
  void writeDigitNum(uint8_t x, uint8_t num, boolean dot = false);
  void drawColon(boolean state);
  void printNumber(long, uint8_t = 2);
  void printFloat(double, uint8_t = 2, uint8_t = DEC);
  void printError(void);

 private:
  uint8_t position;
};
<commit_msg>Update Adafruit-LEDBackpack.cpp<commit_after>/***************************************************
  This is a library for our I2C LED Backpacks

  Designed specifically to work with the Adafruit LED Matrix backpacks
  ----> http://www.adafruit.com/products/
  ----> http://www.adafruit.com/products/

  These displays use I2C to communicate, 2 pins are required to
  interface. There are multiple selectable I2C addresses. For backpacks
  with 2 Address Select pins: 0x70, 0x71, 0x72 or 0x73. For backpacks
  with 3 Address Select pins: 0x70 thru 0x77

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

/*
#ifdef __AVR_ATtiny85__
 #include <TinyWireM.h>
 #define Wire TinyWireM
#else
 #include <Wire.h>
#endif
*/

#include "Adafruit_LEDBackpack.h"
#include "Adafruit_GFX.h"

static const uint8_t numbertable[] = {
	0x3F, /* 0 */
	0x06, /* 1 */
	0x5B, /* 2 */
	0x4F, /* 3 */
	0x66, /* 4 */
	0x6D, /* 5 */
	0x7D, /* 6 */
	0x07, /* 7 */
	0x7F, /* 8 */
	0x6F, /* 9 */
	0x77, /* a */
	0x7C, /* b */
	0x39, /* C */
	0x5E, /* d */
	0x79, /* E */
	0x71, /* F */
};

void Adafruit_LEDBackpack::setBrightness(uint8_t b) {
  if (b > 15) b = 15;
  Wire.beginTransmission(i2c_addr);
  Wire.write(0xE0 | b);
  Wire.endTransmission();
}

void Adafruit_LEDBackpack::blinkRate(uint8_t b) {
  Wire.beginTransmission(i2c_addr);
  if (b > 3) b = 0; // turn off if not sure

  Wire.write(HT16K33_BLINK_CMD | HT16K33_BLINK_DISPLAYON | (b << 1));
  Wire.endTransmission();
}

Adafruit_LEDBackpack::Adafruit_LEDBackpack(void) {
}

void Adafruit_LEDBackpack::begin(uint8_t _addr = 0x70) {
  i2c_addr = _addr;

  Wire.begin();

  Wire.beginTransmission(i2c_addr);
  Wire.write(0x21);  // turn on oscillator
  Wire.endTransmission();
  blinkRate(HT16K33_BLINK_OFF);

  setBrightness(15); // max brightness
}

void Adafruit_LEDBackpack::writeDisplay(void) {
  Wire.beginTransmission(i2c_addr);
  Wire.write((uint8_t)0x00); // start at address $00

  for (uint8_t i=0; i<8; i++) {
    Wire.write(displaybuffer[i] & 0xFF);
    Wire.write(displaybuffer[i] >> 8);
  }
  Wire.endTransmission();
}

void Adafruit_LEDBackpack::clear(void) {
  for (uint8_t i=0; i<8; i++) {
    displaybuffer[i] = 0;
  }
}

/******************************* 24 BARGRAPH OBJECT */

Adafruit_24bargraph::Adafruit_24bargraph(void) {

}

void Adafruit_24bargraph::setBar(uint8_t bar, uint8_t color) {
  uint16_t a, c;

  if (bar < 12)
    c = bar / 4;
  else
    c = (bar - 12) / 4;

  a = bar % 4;
  if (bar >= 12)
    a += 4;

  //Serial.print("Ano = "); Serial.print(a); Serial.print(" Cath = "); Serial.println(c);
  if (color == LED_RED) {
    displaybuffer[c] |= _BV(a) ;
  } else if (color == LED_YELLOW) {
    displaybuffer[c] |= _BV(a) | _BV(a+8);
  } else if (color == LED_OFF) {
    displaybuffer[c] &= ~_BV(a) & ~_BV(a+8);
  } else if (color == LED_GREEN) {
    displaybuffer[c] |= _BV(a+8) ;
  }
}

/******************************* 8x8 MATRIX OBJECT */

Adafruit_8x8matrix::Adafruit_8x8matrix(void) : Adafruit_GFX(8, 8) {
}

void Adafruit_8x8matrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((y < 0) || (y >= 8)) return;
  if ((x < 0) || (x >= 8)) return;

 // check rotation, move pixel around if necessary
  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = 8 - x - 1;
    break;
  case 2:
    x = 8 - x - 1;
    y = 8 - y - 1;
    break;
  case 3:
    swap(x, y);
    y = 8 - y - 1;
    break;
  }

  // wrap around the x
  x += 7;
  x %= 8;

  if (color) {
    displaybuffer[y] |= 1 << x;
  } else {
    displaybuffer[y] &= ~(1 << x);
  }
}

/******************************* 8x8 BICOLOR MATRIX OBJECT */

Adafruit_BicolorMatrix::Adafruit_BicolorMatrix(void) : Adafruit_GFX(8, 8) {
}

void Adafruit_BicolorMatrix::drawPixel(int16_t x, int16_t y, uint16_t color) {
  if ((y < 0) || (y >= 8)) return;
  if ((x < 0) || (x >= 8)) return;

  switch (getRotation()) {
  case 1:
    swap(x, y);
    x = 8 - x - 1;
    break;
  case 2:
    x = 8 - x - 1;
    y = 8 - y - 1;
    break;
  case 3:
    swap(x, y);
    y = 8 - y - 1;
    break;
  }

  if (color == LED_GREEN) {
    displaybuffer[y] |= 1 << x;
  } else if (color == LED_RED) {
    displaybuffer[y] |= 1 << (x+8);
  } else if (color == LED_YELLOW) {
    displaybuffer[y] |= (1 << (x+8)) | (1 << x);
  } else if (color == LED_OFF) {
    displaybuffer[y] &= ~(1 << x) & ~(1 << (x+8));
  }
}

/******************************* 7 SEGMENT OBJECT */

Adafruit_7segment::Adafruit_7segment(void) {
  position = 0;
}

void Adafruit_7segment::print(unsigned long n, int base)
{
  if (base == 0) write(n);
  else printNumber(n, base);
}

void Adafruit_7segment::print(char c, int base)
{
  print((long) c, base);
}

void Adafruit_7segment::print(unsigned char b, int base)
{
  print((unsigned long) b, base);
}

void Adafruit_7segment::print(int n, int base)
{
  print((long) n, base);
}

void Adafruit_7segment::print(unsigned int n, int base)
{
  print((unsigned long) n, base);
}

void  Adafruit_7segment::println(void) {
  position = 0;
}

void  Adafruit_7segment::println(char c, int base)
{
  print(c, base);
  println();
}

void  Adafruit_7segment::println(unsigned char b, int base)
{
  print(b, base);
  println();
}

void  Adafruit_7segment::println(int n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(unsigned int n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(long n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(unsigned long n, int base)
{
  print(n, base);
  println();
}

void  Adafruit_7segment::println(double n, int digits)
{
  print(n, digits);
  println();
}

void  Adafruit_7segment::print(double n, int digits)
{
  printFloat(n, digits);
}

size_t Adafruit_7segment::write(uint8_t c) {

  uint8_t r = 0;

  if (c == '\n') position = 0;
  if (c == '\r') position = 0;

  if ((c >= '0') && (c <= '9')) {
    writeDigitNum(position, c-'0');
    r = 1;
  }

  position++;
  if (position == 2) position++;

  return r;
}

void Adafruit_7segment::writeDigitRaw(uint8_t d, uint8_t bitmask) {
  if (d > 4) return;
  displaybuffer[d] = bitmask;
}

void Adafruit_7segment::drawColon(boolean state) {
  if (state)
    displaybuffer[2] = 0xFF;
  else
    displaybuffer[2] = 0;
}

void Adafruit_7segment::writeDigitNum(uint8_t d, uint8_t num, boolean dot) {
  if (d > 4) return;

  writeDigitRaw(d, numbertable[num] | (dot << 7));
}

void Adafruit_7segment::print(long n, int base)
{
  printNumber(n, base);
}

void Adafruit_7segment::printNumber(long n, uint8_t base)
{
    printFloat(n, 0, base);
}

void Adafruit_7segment::printFloat(double n, uint8_t fracDigits, uint8_t base)
{
  uint8_t numericDigits = 4;   // available digits on display
  boolean isNegative = false;  // true if the number is negative

  // is the number negative?
  if(n < 0) {
    isNegative = true;  // need to draw sign later
    --numericDigits;    // the sign will take up one digit
    n *= -1;            // pretend the number is positive
  }

  // calculate the factor required to shift all fractional digits
  // into the integer part of the number
  double toIntFactor = 1.0;
  for(int i = 0; i < fracDigits; ++i) toIntFactor *= base;

  // create integer containing digits to display by applying
  // shifting factor and rounding adjustment
  uint32_t displayNumber = n * toIntFactor + 0.5;

  // calculate upper bound on displayNumber given
  // available digits on display
  uint32_t tooBig = 1;
  for(int i = 0; i < numericDigits; ++i) tooBig *= base;

  // if displayNumber is too large, try fewer fractional digits
  while(displayNumber >= tooBig) {
    --fracDigits;
    toIntFactor /= base;
    displayNumber = n * toIntFactor + 0.5;
  }

  // did toIntFactor shift the decimal off the display?
  if (toIntFactor < 1) {
    printError();
  } else {
    // otherwise, display the number
    int8_t displayPos = 4;

    if (displayNumber)  //if displayNumber is not 0
    {
      for(uint8_t i = 0; displayNumber; ++i) {
        boolean displayDecimal = (fracDigits != 0 && i == fracDigits);
        writeDigitNum(displayPos--, displayNumber % base, displayDecimal);
        if(displayPos == 2) writeDigitRaw(displayPos--, 0x00);
        displayNumber /= base;
      }
    }
    else {
      writeDigitNum(displayPos--, 0, false);
    }

    // display negative sign if negative
    if(isNegative) writeDigitRaw(displayPos--, 0x40);

    // clear remaining display positions
    while(displayPos >= 0) writeDigitRaw(displayPos--, 0x00);
  }
}

void Adafruit_7segment::printError(void) {
  for(uint8_t i = 0; i < SEVENSEG_DIGITS; ++i) {
    writeDigitRaw(i, (i == 2 ? 0x00 : 0x40));
  }
}
<|endoftext|>


<commit_before>//! @Alan
//!
//! Exercise 7.2:
//! Add the combine and isbn members to the Sales_data class you wrote for
//! the exercises in § 2.6.2 (p. 76).
//!
//! Exercise 7.3:
//! Revise your transaction-processing program from § 7.1.1 (p. 256)
//! to use these members.
//!

#include <iostream>
#include <string>

using namespace std;

struct wy_Sales_data
{
    std::string bookNo;
    unsigned units_sold = 1;
    double revenue = 5.7;

    //!
    //! @brief   Exercise 7.2
    //! @note    combine and isbn members
    //!
    std::string isbn(void) const {return this->bookNo;}
    //! @attention         ^^^^^
    //  const placed following member function means to return a const this pointer.

    wy_Sales_data &combine (const wy_Sales_data &sd);
};
//!
//! @brief  Exercise 7.3
//! @note   ransaction-processing program revised.
//!
int main()
{
    wy_Sales_data total;

    if(cin>>total.bookNo && total.bookNo.size()>1)
    {
        wy_Sales_data trans;

        while(cin>>trans.bookNo && trans.bookNo.size()>1)
        {
            if(total.bookNo == trans.bookNo)
            {
                //! previous codes:
                //  total.units_sold ++;
                //  total.revenue +=5.7;

                total.combine(trans);
            }
            else
            {
                //! previous codes:
                //  cout<<total.bookNo

                cout<<total.isbn()
                   <<":\ntotal sold="<<total.units_sold
                  <<"\ntotal revenue="<<total.revenue
                 <<std::endl;

                total = trans;
            }
        }

        //! previous codes:
        //  cout<<total.bookNo

        cout<<total.isbn()
           <<":\ntotal sold="<<total.units_sold
          <<"\ntotal revenue="<<total.revenue
         <<std::endl;
    }
    else
    {
        cerr << "No data?!" << endl;
    }

    return 0;
}

//!
//! @brief   Exercise 7.2
//! @note    combine and isbn members,definitions.
//!
wy_Sales_data &wy_Sales_data::combine(const wy_Sales_data &sd)
{
    this->revenue += sd.revenue;
    this->units_sold += sd.units_sold;

    return *this;
}
<commit_msg>Delete ex7_2_3.cpp<commit_after><|endoftext|>