text:
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail 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)
//
// Official repository: https://github.com/boostorg/beast
//

#ifndef BOOST_BEAST_HTTP_IMPL_CHUNK_ENCODE_HPP
#define BOOST_BEAST_HTTP_IMPL_CHUNK_ENCODE_HPP

#include <boost/beast/core/buffer_traits.hpp>
#include <boost/beast/core/detail/varint.hpp>
#include <boost/beast/http/error.hpp>
#include <boost/beast/http/detail/rfc7230.hpp>
#include <algorithm>

namespace boost {
namespace beast {
namespace http {

inline
chunk_header::
chunk_header(std::size_t size)
    : view_(
        size,
        net::const_buffer{nullptr, 0},
        chunk_crlf{})
{
    BOOST_ASSERT(size > 0);
}

inline
chunk_header::
chunk_header(
    std::size_t size,
    string_view extensions)
    : view_(
        size,
        net::const_buffer{
            extensions.data(), extensions.size()},
        chunk_crlf{})
{
    BOOST_ASSERT(size > 0);
}

template<class ChunkExtensions, class>
chunk_header::
chunk_header(
    std::size_t size,
    ChunkExtensions&& extensions)
    : exts_(std::make_shared<detail::chunk_extensions_impl<
        typename std::decay<ChunkExtensions>::type>>(
            std::forward<ChunkExtensions>(extensions)))
    , view_(
        size,
        exts_->str(),
        chunk_crlf{})
{
    static_assert(
        detail::is_chunk_extensions<ChunkExtensions>::value,
        "ChunkExtensions requirements not met");
    BOOST_ASSERT(size > 0);
}

template<class ChunkExtensions, class Allocator, class>
chunk_header::
chunk_header(
    std::size_t size,
    ChunkExtensions&& extensions,
    Allocator const& allocator)
    : exts_(std::allocate_shared<detail::chunk_extensions_impl<
        typename std::decay<ChunkExtensions>::type>>(allocator,
            std::forward<ChunkExtensions>(extensions)))
    , view_(
        size,
        exts_->str(),
        chunk_crlf{})
{
    static_assert(
        detail::is_chunk_extensions<ChunkExtensions>::value,
        "ChunkExtensions requirements not met");
    BOOST_ASSERT(size > 0);
}

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

template<class ConstBufferSequence>
chunk_body<ConstBufferSequence>::
chunk_body(ConstBufferSequence const& buffers)
    : view_(
        buffer_bytes(buffers),
        net::const_buffer{nullptr, 0},
        chunk_crlf{},
        buffers,
        chunk_crlf{})
{
}

template<class ConstBufferSequence>
chunk_body<ConstBufferSequence>::
chunk_body(
    ConstBufferSequence const& buffers,
    string_view extensions)
    : view_(
        buffer_bytes(buffers),
        net::const_buffer{
            extensions.data(), extensions.size()},
        chunk_crlf{},
        buffers,
        chunk_crlf{})
{
}

template<class ConstBufferSequence>
template<class ChunkExtensions, class>
chunk_body<ConstBufferSequence>::
chunk_body(
    ConstBufferSequence const& buffers,
    ChunkExtensions&& extensions)
    : exts_(std::make_shared<detail::chunk_extensions_impl<
        typename std::decay<ChunkExtensions>::type>>(
            std::forward<ChunkExtensions>(extensions)))
    , view_(
        buffer_bytes(buffers),
        exts_->str(),
        chunk_crlf{},
        buffers,
        chunk_crlf{})
{
}

template<class ConstBufferSequence>
template<class ChunkExtensions, class Allocator, class>
chunk_body<ConstBufferSequence>::
chunk_body(
    ConstBufferSequence const& buffers,
    ChunkExtensions&& extensions,
    Allocator const& allocator)
    : exts_(std::allocate_shared<detail::chunk_extensions_impl<
        typename std::decay<ChunkExtensions>::type>>(allocator,
            std::forward<ChunkExtensions>(extensions)))
    , view_(
        buffer_bytes(buffers),
        exts_->str(),
        chunk_crlf{},
        buffers,
        chunk_crlf{})
{
}

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

template<class Trailer>
template<class Allocator>
auto
chunk_last<Trailer>::
prepare(Trailer const& trailer, Allocator const& allocator) ->
    buffers_type
{
    auto sp = std::allocate_shared<typename
        Trailer::writer>(allocator, trailer);
    sp_ = sp;
    return sp->get();
}

template<class Trailer>
auto
chunk_last<Trailer>::
prepare(Trailer const& trailer, std::true_type) ->
    buffers_type
{
    auto sp = std::make_shared<
        typename Trailer::writer>(trailer);
    sp_ = sp;
    return sp->get();
}

template<class Trailer>
auto
chunk_last<Trailer>::
prepare(Trailer const& trailer, std::false_type) ->
    buffers_type
{
    return trailer;
}

template<class Trailer>
chunk_last<Trailer>::
chunk_last()
    : view_(
        detail::chunk_size0{},
        Trailer{})
{
}

template<class Trailer>
chunk_last<Trailer>::
chunk_last(Trailer const& trailer)
    : view_(
        detail::chunk_size0{},
        prepare(trailer, is_fields<Trailer>{}))
{
}

template<class Trailer>
template<class DeducedTrailer, class Allocator, class>
chunk_last<Trailer>::
chunk_last(
    DeducedTrailer const& trailer, Allocator const& allocator)
    : view_(
        detail::chunk_size0{},
        prepare(trailer, allocator))
{
}

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

template<class Allocator>
class basic_chunk_extensions<Allocator>::const_iterator
{
    friend class basic_chunk_extensions;

    using iter_type = char const*;

    iter_type it_;
    typename basic_chunk_extensions::value_type value_;

    explicit
    const_iterator(iter_type it)
        : it_(it)
    {
    }

    void
    increment();

public:
    using value_type = typename
        basic_chunk_extensions::value_type;
    using pointer = value_type const*;
    using reference = value_type const&;
    using difference_type = std::ptrdiff_t;
    using iterator_category =
        std::forward_iterator_tag;

    const_iterator() = default;
    const_iterator(const_iterator&& other) = default;
    const_iterator(const_iterator const& other) = default;
    const_iterator& operator=(const_iterator&& other) = default;
    const_iterator& operator=(const_iterator const& other) = default;

    bool
    operator==(const_iterator const& other) const
    {
        return it_ == other.it_;
    }

    bool
    operator!=(const_iterator const& other) const
    {
        return !(*this == other);
    }

    reference
    operator*();

    pointer
    operator->()
    {
        return &(**this);
    }

    const_iterator&
    operator++()
    {
        increment();
        return *this;
    }

    const_iterator
    operator++(int)
    {
        auto temp = *this;
        increment();
        return temp;
    }
};

template<class Allocator>
void
basic_chunk_extensions<Allocator>::
const_iterator::
increment()
{
    using beast::detail::varint_read;
    auto n = varint_read(it_);
    it_ += n;
    n = varint_read(it_);
    it_ += n;
}

template<class Allocator>
auto
basic_chunk_extensions<Allocator>::
const_iterator::
operator*() ->
    reference
{
    using beast::detail::varint_read;
    auto it = it_;
    auto n = varint_read(it);
    value_.first = string_view{it, n};
    it += n;
    n = varint_read(it);
    value_.second = string_view{it, n};
    return value_;
}

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

template<class Allocator>
template<class FwdIt>
FwdIt
basic_chunk_extensions<Allocator>::
do_parse(FwdIt it, FwdIt last, error_code& ec)
{
/*
    chunk-ext       = *( BWS  ";" BWS chunk-ext-name [ BWS  "=" BWS chunk-ext-val ] )
    BWS             = *( SP / HTAB ) ; "Bad White Space"
    chunk-ext-name  = token
    chunk-ext-val   = token / quoted-string
    token           = 1*tchar
    quoted-string   = DQUOTE *( qdtext / quoted-pair ) DQUOTE
    qdtext          = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
    quoted-pair     = "\" ( HTAB / SP / VCHAR / obs-text )
    obs-text        = %x80-FF

    https://www.rfc-editor.org/errata_search.php?rfc=7230&eid=4667
*/
    using beast::detail::varint_size;
    using beast::detail::varint_write;
    using CharT = char;
    using Traits = std::char_traits<CharT>;
    range_.reserve(static_cast<std::size_t>(
        std::distance(it, last) * 1.2));
    range_.resize(0);
    auto const emit_string =
        [this](FwdIt from, FwdIt to)
        {
            auto const len =
                std::distance(from, to);
            auto const offset = range_.size();
            range_.resize(
                offset +
                varint_size(len) +
                len);
            auto dest = &range_[offset];
            varint_write(dest, len);
            Traits::copy(dest, from, len);
        };
    auto const emit_string_plus_empty =
        [this](FwdIt from, FwdIt to)
        {
            auto const len =
                std::distance(from, to);
            auto const offset = range_.size();
            range_.resize(
                offset +
                varint_size(len) +
                len +
                varint_size(0));
            auto dest = &range_[offset];
            varint_write(dest, len);
            Traits::copy(dest, from, len);
            dest += len;
            varint_write(dest, 0);
        };
    auto const emit_empty_string =
        [this]
        {
            auto const offset = range_.size();
            range_.resize(offset + varint_size(0));
            auto dest = &range_[offset];
            varint_write(dest, 0);
        };
loop:
    if(it == last)
    {
        ec = {};
        return it;
    }
    // BWS
    if(*it == ' ' || *it == '\t')
    {
        for(;;)
        {
            ++it;
            if(it == last)
            {
                ec = error::bad_chunk_extension;
                return it;
            }
            if(*it != ' ' && *it != '\t')
                break;
        }
    }
    // ';'
    if(*it != ';')
    {
        ec = error::bad_chunk_extension;
        return it;
    }
semi:
    ++it; // skip ';'
    // BWS
    for(;;)
    {
        if(it == last)
        {
            ec = error::bad_chunk_extension;
            return it;
        }
        if(*it != ' ' && *it != '\t')
            break;
        ++it;
    }
    // chunk-ext-name
    {
        if(! detail::is_token_char(*it))
        {
            ec = error::bad_chunk_extension;
            return it;
        }
        auto const first = it;
        for(;;)
        {
            ++it;
            if(it == last)
            {
                emit_string_plus_empty(first, it);
                return it;
            }
            if(! detail::is_token_char(*it))
                break;
        }
        emit_string(first, it);
    }
    // BWS [ ";" / "=" ]
    for(;;)
    {
        if(*it != ' ' && *it != '\t')
            break;
        ++it;
        if(it == last)
        {
            ec = error::bad_chunk_extension;
            return it;
        }
    }
    if(*it == ';')
    {
        emit_empty_string();
        goto semi;
    }
    if(*it != '=')
    {
        ec = error::bad_chunk_extension;
        return it;
    }
    ++it; // skip '='
    // BWS
    for(;;)
    {
        if(it == last)
        {
            ec = error::bad_chunk_extension;
            return it;
        }
        if(*it != ' ' && *it != '\t')
            break;
        ++it;
    }
    // chunk-ext-val
    if(*it != '"')
    {
        // token
        if(! detail::is_token_char(*it))
        {
            ec = error::bad_chunk_extension;
            return it;
        }
        auto const first = it;
        for(;;)
        {
            ++it;
            if(it == last)
                break;
            if(! detail::is_token_char(*it))
                break;
        }
        emit_string(first, it);
        if(it == last)
            return it;
    }
    else
    {
        // quoted-string
        auto const first = ++it; // skip DQUOTE
        // first pass, count chars
        std::size_t len = 0;
        for(;;)
        {
            if(it == last)
            {
                ec = error::bad_chunk_extension;
                return it;
            }
            if(*it == '"')
                break;
            if(*it == '\\')
            {
                ++it;
                if(it == last)
                {
                    ec = error::bad_chunk_extension;
                    return it;
                }
            }
            ++len;
            ++it;
        }
        // now build the string
        auto const offset = range_.size();
        range_.resize(
            offset +
            varint_size(len) +
            len);
        auto dest = &range_[offset];
        varint_write(dest, len);
        it = first;
        for(;;)
        {
            BOOST_ASSERT(it != last);
            if(*it == '"')
                break;
            if(*it == '\\')
            {
                ++it;
                BOOST_ASSERT(it != last);
            }
            Traits::assign(*dest++, *it++);
        }
        ++it; // skip DQUOTE
    }
    goto loop;
}

template<class Allocator>
void
basic_chunk_extensions<Allocator>::
do_insert(string_view name, string_view value)
{
/*
    chunk-ext       = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
    chunk-ext-name  = token
    chunk-ext-val   = token / quoted-string
    token           = 1*tchar
    quoted-string   = DQUOTE *( qdtext / quoted-pair ) DQUOTE
    qdtext          = HTAB / SP / "!" / %x23-5B ; '#'-'[' / %x5D-7E ; ']'-'~' / obs-text
    quoted-pair     = "\" ( HTAB / SP / VCHAR / obs-text )
    obs-text        = %x80-FF
*/
    if(value.empty())
    {
        s_.reserve(1 + name.size());
        s_.push_back(';');
        s_.append(name.data(), name.size());
        return;
    }

    bool is_token = true;
    for(auto const c : value)
    {
        if(! detail::is_token_char(c))
        {
            is_token = false;
            break;
        }
    }
    if(is_token)
    {
        // token
        s_.reserve(1 + name.size() + 1 + value.size());
        s_.push_back(';');
        s_.append(name.data(), name.size());
        s_.push_back('=');
        s_.append(value.data(), value.size());
    }
    else
    {
        // quoted-string
        s_.reserve(
            1 + name.size() + 1 +
            1 + value.size() + 20 + 1);
        s_.push_back(';');
        s_.append(name.data(), name.size());
        s_.append("=\"", 2);
        for(auto const c : value)
        {
            if(c == '\\')
                s_.append(R"(\\)", 2);
            else if(c == '\"')
                s_.append(R"(\")", 2);
            else
                s_.push_back(c);
        }
        s_.push_back('"');
    }
}

template<class Allocator>
void
basic_chunk_extensions<Allocator>::
parse(string_view s, error_code& ec)
{
    do_parse(s.data(), s.data() + s.size(), ec);
    if(! ec)
    {
        s_.clear();
        for(auto const& v : *this)
            do_insert(v.first, v.second);
    }
}

template<class Allocator>
void
basic_chunk_extensions<Allocator>::
insert(string_view name)
{
    do_insert(name, {});

    using beast::detail::varint_size;
    using beast::detail::varint_write;
    auto const offset = range_.size();
    range_.resize(
        offset +
        varint_size(name.size()) +
        name.size() +
        varint_size(0));
    auto dest = &range_[offset];
    varint_write(dest, name.size());
    std::memcpy(dest, name.data(), name.size());
    dest += name.size();
    varint_write(dest, 0);
}

template<class Allocator>
void
basic_chunk_extensions<Allocator>::
insert(string_view name, string_view value)
{
    do_insert(name, value);

    using beast::detail::varint_size;
    using beast::detail::varint_write;
    auto const offset = range_.size();
    range_.resize(
        offset +
        varint_size(name.size()) +
        name.size() +
        varint_size(value.size()) +
        value.size());
    auto dest = &range_[offset];
    varint_write(dest, name.size());
    std::memcpy(dest, name.data(), name.size());
    dest += name.size();
    varint_write(dest, value.size());
    std::memcpy(dest, value.data(), value.size());
}

template<class Allocator>
auto
basic_chunk_extensions<Allocator>::
begin() const ->
    const_iterator
{
    return const_iterator{range_.data()};
}

template<class Allocator>
auto
basic_chunk_extensions<Allocator>::
end() const ->
    const_iterator
{
    return const_iterator{
        range_.data() + range_.size()};
}

} // http
} // beast
} // boost

#endif

max_stars_repo_name: kindlychung/mediasoup-sfu-cpp

max_issues_repo_name: kindlychung/mediasoup-sfu-cpp

max_forks_repo_name: kindlychung/mediasoup-sfu-cpp


text:
//  Copyright (c) 2006, Giovanni P. Deretta
//
//  This code may be used under either of the following two licences:
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
//  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//  THE SOFTWARE. OF SUCH DAMAGE.
//
//  Or:
//
//  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)

#ifndef HPX_RUNTIME_THREADS_COROUTINES_DETAIL_CONTEXT_POSIX_HPP
#define HPX_RUNTIME_THREADS_COROUTINES_DETAIL_CONTEXT_POSIX_HPP

// NOTE (per http://lists.apple.com/archives/darwin-dev/2008/Jan/msg00232.html):
// > Why the bus error? What am I doing wrong?
// This is a known issue where getcontext(3) is writing past the end of the
// ucontext_t struct when _XOPEN_SOURCE is not defined (rdar://problem/5578699 ).
// As a workaround, define _XOPEN_SOURCE before including ucontext.h.
#if defined(__APPLE__) && ! defined(_XOPEN_SOURCE)
#define _XOPEN_SOURCE
// However, the above #define will only affect <ucontext.h> if it has not yet
// been #included by something else!
#if defined(_STRUCT_UCONTEXT)
#error You must #include coroutine headers before anything that #includes <ucontext.h>
#endif
#endif

#include <hpx/util/assert.hpp>
#include <hpx/util/get_and_reset_value.hpp>
#include <hpx/util/unused.hpp>

#include <boost/atomic.hpp>

#if defined(__FreeBSD__) || (defined(_XOPEN_UNIX) && defined(_XOPEN_VERSION) \
            && _XOPEN_VERSION >= 500)

// OS X 10.4 -- despite passing the test above -- doesn't support
// swapcontext() et al. Use GNU Pth workalike functions.
#if defined(__APPLE__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1050)

#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <limits>
#include "pth/pth.h"

namespace hpx { namespace threads { namespace coroutines { namespace detail {
namespace posix { namespace pth
{
    inline int check(int rc)
    {
        // The makecontext() functions return zero for success, nonzero for
        // error. The Pth library returns TRUE for success, FALSE for error,
        // with errno set to the nonzero error in the latter case. Map the Pth
        // returns to ucontext style.
        return rc? 0 : errno;
    }
}}
}}}}

#define HPX_COROUTINE_POSIX_IMPL "Pth implementation"
#define HPX_COROUTINE_DECLARE_CONTEXT(name) pth_uctx_t name
#define HPX_COROUTINE_CREATE_CONTEXT(ctx)                                     \
    hpx::threads::coroutines::detail::posix::pth::check(pth_uctx_create(&(ctx)))
#define HPX_COROUTINE_MAKE_CONTEXT(ctx, stack, size, startfunc, startarg, exitto) \
    /* const sigset_t* sigmask = nullptr: we don't expect per-context signal masks */ \
    hpx::threads::coroutines::detail::posix::pth::check(                      \
        pth_uctx_make(*(ctx), static_cast<char*>(stack), (size), nullptr,        \
        (startfunc), (startarg), (exitto)))
#define HPX_COROUTINE_SWAP_CONTEXT(from, to)                                  \
    hpx::threads::coroutines::detail::posix::pth::check(pth_uctx_switch(*(from), *(to)))
#define HPX_COROUTINE_DESTROY_CONTEXT(ctx)                                    \
    hpx::threads::coroutines::detail::posix::pth::check(pth_uctx_destroy(ctx))

#else // generic Posix platform (e.g. OS X >= 10.5)

/*
 * makecontext based context implementation. Should be available on all
 * SuSv2 compliant UNIX systems.
 * NOTE: this implementation is not
 * optimal as the makecontext API saves and restore the signal mask.
 * This requires a system call for every context switch that really kills
 * performance. Still is very portable and guaranteed to work.
 * NOTE2: makecontext and friends are declared obsolescent in SuSv3, but
 * it is unlikely that they will be removed any time soon.
 */
#include <cstddef>                  // ptrdiff_t
#include <ucontext.h>

#if defined(HPX_HAVE_THREAD_STACKOVERFLOW_DETECTION)

#include <signal.h>
#include <stdlib.h>
#include <strings.h>
#include <cstring>

#ifndef SEGV_STACK_SIZE
  #define SEGV_STACK_SIZE MINSIGSTKSZ+4096
#endif

#endif

#include <iostream>
#include <iomanip>

namespace hpx { namespace threads { namespace coroutines { namespace detail {
namespace posix { namespace ucontext
{
    inline int make_context(::ucontext_t* ctx, void* stack, std::ptrdiff_t size,
                            void (*startfunc)(void*), void* startarg,
                            ::ucontext_t* exitto = nullptr)
    {
        int error = ::getcontext(ctx);
        if (error)
            return error;

        ctx->uc_stack.ss_sp = (char*)stack;
        ctx->uc_stack.ss_size = size;
        ctx->uc_link = exitto;

        typedef void (*ctx_main)();
        //makecontext can't fail.
        ::makecontext(ctx,
                      (ctx_main)(startfunc),
                      1,
                      startarg);
        return 0;
    }
}}
}}}}

#define HPX_COROUTINE_POSIX_IMPL "ucontext implementation"
#define HPX_COROUTINE_DECLARE_CONTEXT(name) ::ucontext_t name
#define HPX_COROUTINE_CREATE_CONTEXT(ctx) /* nop */
#define HPX_COROUTINE_MAKE_CONTEXT(ctx, stack, size, startfunc, startarg, exitto) \
    hpx::threads::coroutines::detail::posix::ucontext::make_context(          \
        ctx, stack, size, startfunc, startarg, exitto)
#define HPX_COROUTINE_SWAP_CONTEXT(pfrom, pto) ::swapcontext((pfrom), (pto))
#define HPX_COROUTINE_DESTROY_CONTEXT(ctx) /* nop */

#endif // generic Posix platform

#include <hpx/runtime/threads/coroutines/detail/get_stack_pointer.hpp>
#include <hpx/runtime/threads/coroutines/detail/posix_utility.hpp>
#include <hpx/runtime/threads/coroutines/detail/swap_context.hpp>
#include <hpx/runtime/threads/coroutines/exception.hpp>
#include <signal.h>                 // SIGSTKSZ

namespace hpx { namespace threads { namespace coroutines
{
    // some platforms need special preparation of the main thread
    struct prepare_main_thread
    {
        prepare_main_thread() {}
        ~prepare_main_thread() {}
    };

    namespace detail { namespace posix
    {
        /*
         * Posix implementation for the context_impl_base class.
         * @note context_impl is not required to be consistent
         * If not initialized it can only be swapped out, not in
         * (at that point it will be initialized).
         *
         */
        class ucontext_context_impl_base : detail::context_impl_base
        {
        public:
            ucontext_context_impl_base()
            {
                HPX_COROUTINE_CREATE_CONTEXT(m_ctx);
            }
            ~ucontext_context_impl_base()
            {
                HPX_COROUTINE_DESTROY_CONTEXT(m_ctx);
            }

        private:
            /*
             * Free function. Saves the current context in @p from
             * and restores the context in @p to.
             */
            friend void swap_context(ucontext_context_impl_base& from,
                const ucontext_context_impl_base& to, default_hint)
            {
                int  error = HPX_COROUTINE_SWAP_CONTEXT(&from.m_ctx, &to.m_ctx);
                HPX_UNUSED(error);
                HPX_ASSERT(error == 0);
            }

        protected:
            HPX_COROUTINE_DECLARE_CONTEXT(m_ctx);
        };

        class ucontext_context_impl
          : public ucontext_context_impl_base
        {
        public:
            HPX_NON_COPYABLE(ucontext_context_impl);

        public:
            typedef ucontext_context_impl_base context_impl_base;

            enum { default_stack_size = SIGSTKSZ };

            /**
             * Create a context that on restore invokes Functor on
             *  a new stack. The stack size can be optionally specified.
             */
            template<typename Functor>
            explicit ucontext_context_impl(Functor & cb, std::ptrdiff_t stack_size)
              : m_stack_size(stack_size == -1 ? (std::ptrdiff_t)default_stack_size
                    : stack_size),
                m_stack(alloc_stack(m_stack_size)),
                cb_(&cb)
            {
                HPX_ASSERT(m_stack);
                funp_ = &trampoline<Functor>;
                int error = HPX_COROUTINE_MAKE_CONTEXT(
                    &m_ctx, m_stack, m_stack_size, funp_, cb_, nullptr);
                HPX_UNUSED(error);
                HPX_ASSERT(error == 0);

#if defined(HPX_HAVE_THREAD_STACKOVERFLOW_DETECTION)
                // concept inspired by the following links:
                //
                // https://rethinkdb.com/blog/handling-stack-overflow-on-custom-stacks/
                // http://www.evanjones.ca/software/threading.html
                //
                segv_stack.ss_sp = valloc(SEGV_STACK_SIZE);
                segv_stack.ss_flags = 0;
                segv_stack.ss_size = SEGV_STACK_SIZE;

                std::memset(&action, '\0', sizeof(action));
                action.sa_flags = SA_SIGINFO|SA_ONSTACK; //SA_STACK
                action.sa_sigaction = &ucontext_context_impl::sigsegv_handler;

                sigaltstack(&segv_stack, nullptr);
                sigfillset(&action.sa_mask);
                sigaction(SIGSEGV, &action, nullptr);
#endif
            }

#if defined(HPX_HAVE_THREAD_STACKOVERFLOW_DETECTION)
            static void sigsegv_handler(int signum, siginfo_t *info,
                void *data)
            {
                void *addr = info->si_addr;

                std::cerr << "Stack overflow in coroutine at address "
                    << std::internal << std::hex
                    << std::setw(sizeof(addr)*2+2)
                    << std::setfill('0') << static_cast<int*>(addr)
                    << ".\n\n";

                std::cerr
                    << "Configure the hpx runtime to allocate a larger coroutine "
                       "stack size.\n Use the hpx.stacks.small_size, "
                       "hpx.stacks.medium_size,\n hpx.stacks.large_size, "
                       "or hpx.stacks.huge_size configuration\nflags to configure "
                       "coroutine stack sizes.\n"
                    << std::endl;

                std::terminate();
            }
#endif

            ~ucontext_context_impl()
            {
                if (m_stack)
                    free_stack(m_stack, m_stack_size);
            }

            // Return the size of the reserved stack address space.
            std::ptrdiff_t get_stacksize() const
            {
                return m_stack_size;
            }

            std::ptrdiff_t get_available_stack_space()
            {
#if defined(HPX_HAVE_THREADS_GET_STACK_POINTER)
                return get_stack_ptr() - reinterpret_cast<std::size_t>(m_stack);
#else
                return (std::numeric_limits<std::ptrdiff_t>::max)();
#endif
            }

            // global functions to be called for each OS-thread after it started
            // running and before it exits
            static void thread_startup(char const* thread_type) {}
            static void thread_shutdown() {}

            void reset_stack()
            {
                if (m_stack)
                {
                    if (posix::reset_stack(
                        m_stack, static_cast<std::size_t>(m_stack_size)))
                        increment_stack_unbind_count();
                }
            }

            void rebind_stack()
            {
                if (m_stack)
                {
                    // just reset the context stack pointer to its initial value at
                    // the stack start
                    increment_stack_recycle_count();
                    int error = HPX_COROUTINE_MAKE_CONTEXT(
                        &m_ctx, m_stack, m_stack_size, funp_, cb_, nullptr);
                    HPX_UNUSED(error);
                    HPX_ASSERT(error == 0);
                }
            }

            typedef boost::atomic<std::int64_t> counter_type;

            static counter_type& get_stack_unbind_counter()
            {
                static counter_type counter(0);
                return counter;
            }

            static std::uint64_t get_stack_unbind_count(bool reset)
            {
                return util::get_and_reset_value(get_stack_unbind_counter(), reset);
            }

            static std::uint64_t increment_stack_unbind_count()
            {
                return ++get_stack_unbind_counter();
            }

            static counter_type& get_stack_recycle_counter()
            {
                static counter_type counter(0);
                return counter;
            }

            static std::uint64_t get_stack_recycle_count(bool reset)
            {
                return util::get_and_reset_value(get_stack_recycle_counter(), reset);
            }

            static std::uint64_t increment_stack_recycle_count()
            {
                return ++get_stack_recycle_counter();
            }

        private:
            // declare m_stack_size first so we can use it to initialize m_stack
            std::ptrdiff_t m_stack_size;
            void * m_stack;
            void * cb_;
            void(*funp_)(void*);

            struct sigaction action;
            stack_t segv_stack;
        };

        typedef ucontext_context_impl context_impl;
    }}
}}}

#else

/**
 * This #else clause is essentially unchanged from the original Google Summer
 * of Code version of Boost.Coroutine, which comments:
 * "Context swapping can be implemented on most posix systems lacking *context
 * using the signaltstack+longjmp trick."
 * This is in fact what the (highly portable) Pth library does, so if you
 * encounter such a system, perhaps the best approach would be to twiddle the
 * #if logic in this header to use the pth.h implementation above.
 */
#error No context implementation for this POSIX system.

#endif

#endif /*HPX_RUNTIME_THREADS_COROUTINES_DETAIL_CONTEXT_POSIX_HPP*/

ext: hpp

max_stars_repo_name: atrantan/hpx

max_issues_repo_name: atrantan/hpx

max_forks_repo_name: atrantan/hpx


text:
/* Copyright © 2017 Apple Inc. All rights reserved.
 *
 * Use of this source code is governed by a BSD-3-clause license that can
 * be found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
 */
#include <logger/logger.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/array.hpp>
#include <fileio/cache_stream_source.hpp>
#include <fileio/fixed_size_cache_manager.hpp>

namespace turi {
namespace fileio_impl {

cache_stream_source::cache_stream_source(cache_id_type cache_id) {
  auto& cache_manager = fileio::fixed_size_cache_manager::get_instance();
  in_block = cache_manager.get_cache(cache_id);
  if (in_block->is_pointer()) {
    in_array = in_block->get_pointer();
    array_size = in_block->get_pointer_size();
    array_cur_pos = 0;
  } else {
    in_array = NULL;
    array_size = 0;
    array_cur_pos = 0;
    logstream(LOG_INFO) << "Reading " << cache_id << " from "
                        << in_block->get_filename() << std::endl;
    in_file = std::make_shared<general_fstream_source>(in_block->get_filename());
  }
}

std::streamsize cache_stream_source::read(char* c, std::streamsize bufsize) {
  if (in_array) {
    size_t bytes_read = std::min<size_t>(bufsize, array_size - array_cur_pos);
    memcpy(c, in_array + array_cur_pos, bytes_read);
    array_cur_pos += bytes_read;
    return bytes_read;
  } else {
    return in_file->read(c, bufsize);
  }
}

void cache_stream_source::close() {
  if (in_file) {
    in_file->close();
  }
}

std::streampos cache_stream_source::seek(std::streamoff off, std::ios_base::seekdir way) {
  if (in_array) {
    std::streampos newpos;
    if (way == std::ios_base::beg) {
      newpos = off;
    } else if (way == std::ios_base::cur) {
      newpos = (std::streampos)(array_cur_pos) + off;
    } else if (way == std::ios_base::end) {
      newpos = array_size + off - 1;
    }

    if (newpos < 0 || newpos >= (std::streampos)array_size) {
      log_and_throw_io_failure("Bad seek. Index out of range.");
    }

    array_cur_pos = newpos;
    return newpos;
  }

  return in_file->seek(off, way);
}

bool cache_stream_source::is_open() const {
  if (in_file) {
    return in_file->is_open();
  }
  return true;
}

size_t cache_stream_source::file_size() const {
  if (in_file) {
    return in_file->file_size();
  }
  return array_size;
}

std::shared_ptr<std::istream> cache_stream_source::get_underlying_stream() {
  if (in_array) {
    return
        std::make_shared<boost::iostreams::stream<boost::iostreams::array_source>>(
            in_block->get_pointer(), in_block->get_pointer_size());
  } else {
    auto ret = in_file->get_underlying_stream();
    if (ret == nullptr) {
      return std::make_shared<general_ifstream>(in_block->get_filename());
    }
    else return ret;
  }
}

} // fileio_impl
} // turicreate

ext: cpp

max_forks_repo_name: ZeroInfinite/turicreate


text:
// Copyright Takatoshi Kondo 2020
//
// 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)

#if !defined(MQTT_BROKER_SESSION_STATE_HPP)
#define MQTT_BROKER_SESSION_STATE_HPP

#include <mqtt/config.hpp>

#include <chrono>

#include <boost/asio/io_context.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>

#include <mqtt/broker/broker_namespace.hpp>

#include <mqtt/broker/common_type.hpp>
#include <mqtt/broker/sub_con_map.hpp>
#include <mqtt/broker/shared_target.hpp>
#include <mqtt/broker/property_util.hpp>
#include <mqtt/broker/tags.hpp>
#include <mqtt/broker/inflight_message.hpp>
#include <mqtt/broker/offline_message.hpp>

MQTT_BROKER_NS_BEGIN

namespace as = boost::asio;
namespace mi = boost::multi_index;

class session_states;

/**
 * http://docs.oasis-open.org/mqtt/mqtt/v5.0/cs02/mqtt-v5.0-cs02.html#_Session_State
 *
 * 4.1 Session State
 * In order to implement QoS 1 and QoS 2 protocol flows the Client and Server need to associate state with the Client Identifier, this is referred to as the Session State. The Server also stores the subscriptions as part of the Session State.
 * The session can continue across a sequence of Network Connections. It lasts as long as the latest Network Connection plus the Session Expiry Interval.
 * The Session State in the Server consists of:
 * · The existence of a Session, even if the rest of the Session State is empty.
 * · The Clients subscriptions, including any Subscription Identifiers.
 * · QoS 1 and QoS 2 messages which have been sent to the Client, but have not been completely acknowledged.
 * · QoS 1 and QoS 2 messages pending transmission to the Client and OPTIONALLY QoS 0 messages pending transmission to the Client.
 * · QoS 2 messages which have been received from the Client, but have not been completely acknowledged.
 * · The Will Message and the Will Delay Interval
 * · If the Session is currently not connected, the time at which the Session will end and Session State will be discarded.
 *
 * Retained messages do not form part of the Session State in the Server, they are not deleted as a result of a Session ending.
 */
struct session_state {
    // TODO: Currently not fully implemented...
    session_state(
        as::io_context& ioc,
        sub_con_map& subs_map,
        shared_target& shared_targets,
        con_sp_t con,
        buffer client_id,
        optional<will> will,
        optional<std::chrono::steady_clock::duration> will_expiry_interval,
        optional<std::chrono::steady_clock::duration> session_expiry_interval = nullopt)
        :ioc_(ioc),
         subs_map_(subs_map),
         shared_targets_(shared_targets),
         con_(force_move(con)),
         client_id_(force_move(client_id)),
         session_expiry_interval_(force_move(session_expiry_interval))
    {
        update_will(ioc, will, will_expiry_interval);
    }

    session_state(session_state&&) = default;

    ~session_state() {
        MQTT_LOG("mqtt_broker", trace)
            << MQTT_ADD_VALUE(address, this)
            << "session destroy";
        clean();
    }

    bool online() const {
        return bool(con_);
    }

    template <typename SessionExpireHandler>
    void become_offline(SessionExpireHandler&& h) {
        BOOST_ASSERT(con_);
        con_->for_each_store_with_life_keeper(
            [this] (store_message_variant msg, any life_keeper) {
                MQTT_LOG("mqtt_broker", trace)
                    << MQTT_ADD_VALUE(address, this)
                    << "store inflight message";

                std::shared_ptr<as::steady_timer> tim_message_expiry;

                MQTT_NS::visit(
                    make_lambda_visitor(
                        [&](v5::basic_publish_message<sizeof(packet_id_t)> const& m) {
                            auto v = get_property<v5::property::message_expiry_interval>(m.props());
                            if (v) {
                                tim_message_expiry =
                                    std::make_shared<as::steady_timer>(ioc_, std::chrono::seconds(v.value().val()));
                                tim_message_expiry->async_wait(
                                    [this, wp = std::weak_ptr<as::steady_timer>(tim_message_expiry)]
                                    (error_code ec) {
                                        if (auto sp = wp.lock()) {
                                            if (!ec) {
                                                erase_inflight_message_by_expiry(sp);
                                            }
                                        }
                                    }
                                );
                            }
                        },
                        [&](auto const&) {}
                    ),
                    msg
                );

                insert_inflight_message(
                    force_move(msg),
                    force_move(life_keeper),
                    force_move(tim_message_expiry)
                );
            }
        );

        reset_con();

        if (session_expiry_interval_ &&
            session_expiry_interval_.value() != std::chrono::seconds(session_never_expire)) {

            MQTT_LOG("mqtt_broker", trace)
                << MQTT_ADD_VALUE(address, this)
                << "session expiry interval timer set";

            tim_session_expiry_ = std::make_shared<as::steady_timer>(ioc_, session_expiry_interval_.value());
            tim_session_expiry_->async_wait(
                [this, wp = std::weak_ptr<as::steady_timer>(tim_session_expiry_), h = std::forward<SessionExpireHandler>(h)]
                (error_code ec) {
                    if (auto sp = wp.lock()) {
                        if (!ec) {
                            MQTT_LOG("mqtt_broker", info)
                                << MQTT_ADD_VALUE(address, this)
                                << "session expired";
                            h(sp);
                        }
                    }
                }
            );
        }
    }

    void renew_session_expiry(optional<std::chrono::steady_clock::duration> v) {
        MQTT_LOG("mqtt_broker", trace)
            << MQTT_ADD_VALUE(address, this)
            << "renew_session expiry";
        session_expiry_interval_ = force_move(v);
        tim_session_expiry_.reset();
    }

    std::shared_ptr<as::steady_timer> const& tim_session_expiry() const {
        return tim_session_expiry_;
    }

    void publish(
        as::io_context& ioc,
        buffer pub_topic,
        buffer contents,
        publish_options pubopts,
        v5::properties props) {

        BOOST_ASSERT(online());

        if (offline_messages_.empty()) {
            auto qos_value = pubopts.get_qos();
            if (qos_value == qos::at_least_once ||
                qos_value == qos::exactly_once) {
                if (auto pid = con_->acquire_unique_packet_id_no_except()) {
                    // TODO: Probably this should be switched to async_publish?
                    //       Given the async_client / sync_client seperation
                    //       and the way they have different function names,
                    //       it wouldn't be possible for broker.hpp to be
                    //       used with some hypothetical "async_server" in the future.
                    con_->publish(pid.value(), pub_topic, contents, pubopts, props);
                    return;
                }
            }
            else {
                con_->publish(pub_topic, contents, pubopts, props);
                return;
            }
        }

        // offline_messages_ is not empty or packet_id_exhausted
        offline_messages_.push_back(
            ioc,
            force_move(pub_topic),
            force_move(contents),
            pubopts,
            force_move(props)
        );
    }

    void deliver(
        as::io_context& ioc,
        buffer pub_topic,
        buffer contents,
        publish_options pubopts,
        v5::properties props) {

        if (online()) {
            publish(
                ioc,
                force_move(pub_topic),
                force_move(contents),
                pubopts,
                force_move(props)
            );
        }
        else {
            offline_messages_.push_back(
                ioc,
                force_move(pub_topic),
                force_move(contents),
                pubopts,
                force_move(props)
            );
        }
    }

    void clean() {
        inflight_messages_.clear();
        offline_messages_.clear();
        qos2_publish_processed_.clear();
        shared_targets_.erase(*this);
        unsubscribe_all();
    }

    void exactly_once_start(packet_id_t packet_id) {
        qos2_publish_processed_.insert(packet_id);
    }

    bool exactly_once_processing(packet_id_t packet_id) const {
        return qos2_publish_processed_.find(packet_id) != qos2_publish_processed_.end();
    }

    void exactly_once_finish(packet_id_t packet_id) {
        qos2_publish_processed_.erase(packet_id);
    }

    template <typename PublishRetainHandler>
    void subscribe(
        buffer share_name,
        buffer topic_filter,
        subscribe_options subopts,
        PublishRetainHandler&& h,
        optional<std::size_t> sid = nullopt
    ) {
        if (!share_name.empty()) {
            shared_targets_.insert(share_name, topic_filter, *this);
        }
        MQTT_LOG("mqtt_broker", trace)
            << MQTT_ADD_VALUE(address, this)
            << "subscribe"
            << " share_name:" << share_name
            << " topic_filter:" << topic_filter
            << " qos:" << subopts.get_qos();

        subscription sub {*this, force_move(share_name), topic_filter, subopts, sid };
        auto handle_ret = subs_map_.insert_or_assign(
            force_move(topic_filter),
            client_id_,
            force_move(sub)
        );

        auto rh = subopts.get_retain_handling();

        if (handle_ret.second) { // insert
            MQTT_LOG("mqtt_broker", trace)
                << MQTT_ADD_VALUE(address, this)
                << "subscription inserted";

            handles_.insert(handle_ret.first);
            if (rh == retain_handling::send ||
                rh == retain_handling::send_only_new_subscription) {
                std::forward<PublishRetainHandler>(h)();
            }
        }
        else { // update
            MQTT_LOG("mqtt_broker", trace)
                << MQTT_ADD_VALUE(address, this)
                << "subscription updated";

            if (rh == retain_handling::send) {
                std::forward<PublishRetainHandler>(h)();
            }
        }
    }

    void unsubscribe(buffer const& share_name, buffer const& topic_filter) {
        if (!share_name.empty()) {
            shared_targets_.erase(share_name, topic_filter, *this);
        }
        auto handle = subs_map_.lookup(topic_filter);
        if (handle) {
            handles_.erase(handle.value());
            subs_map_.erase(handle.value(), client_id_);
        }
    }

    void unsubscribe_all() {
        for (auto const& h : handles_) {
            subs_map_.erase(h, client_id_);
        }
        handles_.clear();
    }

    void update_will(
        as::io_context& ioc,
        optional<MQTT_NS::will> will,
        optional<std::chrono::steady_clock::duration> will_expiry_interval) {
        tim_will_expiry_.reset();
        will_value_ = force_move(will);

        if (will_value_ && will_expiry_interval) {
            tim_will_expiry_ = std::make_shared<as::steady_timer>(ioc, will_expiry_interval.value());
            tim_will_expiry_->async_wait(
                [this, wp = std::weak_ptr<as::steady_timer>(tim_will_expiry_)]
                (error_code ec) {
                    if (auto sp = wp.lock()) {
                        if (!ec) {
                            reset_will();
                        }
                    }
                }
            );
        }
    }

    void reset_will() {
        tim_will_expiry_.reset();
        will_value_ = nullopt;
    }

    void insert_inflight_message(
        store_message_variant msg,
        any life_keeper,
        std::shared_ptr<as::steady_timer> tim_message_expiry
    ) {
        inflight_messages_.insert(
            force_move(msg),
            force_move(life_keeper),
            force_move(tim_message_expiry)
        );
    }

    void send_inflight_messages() {
        BOOST_ASSERT(con_);
        inflight_messages_.send_all_messages(*con_);
    }

    void erase_inflight_message_by_expiry(std::shared_ptr<as::steady_timer> const& sp) {
        inflight_messages_.get<tag_tim>().erase(sp);
    }

    void erase_inflight_message_by_packet_id(packet_id_t packet_id) {
        auto& idx = inflight_messages_.get<tag_pid>();
        idx.erase(packet_id);
    }

    void send_all_offline_messages() {
        BOOST_ASSERT(con_);
        offline_messages_.send_all(*con_);
    }

    void send_offline_messages_by_packet_id_release() {
        BOOST_ASSERT(con_);
        offline_messages_.send_by_packet_id_release(*con_);
    }

    buffer const& client_id() const {
        return client_id_;
    }

    void reset_con() {
        con_.reset();
    }

    void reset_con(con_sp_t con) {
        con_ = force_move(con);
    }

    con_sp_t const& con() const {
        return con_;
    }

    optional<std::chrono::steady_clock::duration> session_expiry_interval() const {
        return session_expiry_interval_;
    }

    optional<MQTT_NS::will>& will() { return will_value_; }
    optional<MQTT_NS::will> const& will() const { return will_value_; }

    std::shared_ptr<as::steady_timer>& get_tim_will_expiry() { return tim_will_expiry_; }

private:
    friend class session_states;

    as::io_context& ioc_;
    std::shared_ptr<as::steady_timer> tim_will_expiry_;
    optional<MQTT_NS::will> will_value_;

    sub_con_map& subs_map_;
    shared_target& shared_targets_;
    con_sp_t con_;
    buffer client_id_;

    optional<std::chrono::steady_clock::duration> will_delay_;
    optional<std::chrono::steady_clock::duration> session_expiry_interval_;
    std::shared_ptr<as::steady_timer> tim_session_expiry_;

    inflight_messages inflight_messages_;
    std::set<packet_id_t> qos2_publish_processed_;

    offline_messages offline_messages_;

    std::set<sub_con_map::handle> handles_; // to efficient remove
};

class session_states {
public:
    template <typename Tag>
    decltype(auto) get() {
        return entries_.get<Tag>();
    }

    template <typename Tag>
    decltype(auto) get() const {
        return entries_.get<Tag>();
    }

    void clear() {
        entries_.clear();
    }

private:
    // The mi_session_online container holds the relevant data about an active connection with the broker.
    // It can be queried either with the clientid, or with the shared pointer to the mqtt endpoint object
    using mi_session_state = mi::multi_index_container<
        session_state,
        mi::indexed_by<
            // non is nullable
            mi::ordered_non_unique<
                mi::tag<tag_con>,
                BOOST_MULTI_INDEX_MEMBER(session_state, con_sp_t, con_)
            >,
            mi::ordered_unique<
                mi::tag<tag_cid>,
                BOOST_MULTI_INDEX_MEMBER(session_state, buffer, client_id_)
            >,
            mi::ordered_non_unique<
                mi::tag<tag_tim>,
                BOOST_MULTI_INDEX_MEMBER(session_state, std::shared_ptr<as::steady_timer>, tim_session_expiry_)
            >
        >
>;

    mi_session_state entries_;
};

MQTT_BROKER_NS_END

#endif // MQTT_BROKER_SESSION_STATE_HPP


text:
/*
** EPITECH PROJECT, 2020
** B-CPP-501-NAN-5-1-rtype-arthur.bertaud
** File description:
** INetwork.hpp
*/

#ifndef INETWORK_HPP_
#define INETWORK_HPP_

#include <boost/system/error_code.hpp>

class INetwork {
    public:
        virtual ~INetwork() = default;
        virtual void start() = 0;
        virtual void stop() = 0;
    protected:
    private:
        virtual void startReceive() = 0;
        virtual void send(const std::string&) = 0;
        virtual void handleReceive(const boost::system::error_code&, std::size_t) = 0;
};

#endif /* !INETWORK_HPP_ */


text:
#include "kcalpmk.h"

#include "kprogressbar.h"
#include "common.h"

#include <boost/math/special_functions/round.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/powm1.hpp>

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>

#include <QFile>

#include <iostream>
#include <fstream>
#include <limits>

vector<map<vector<int>,long> > KCalPMK::sIndex_map;
vector<long> KCalPMK::sNowIndex;
QString KCalPMK::sMapIndexFile="";

// static function
bool KCalPMK::readMapIndex(QString filename)
{
    sMapIndexFile = filename;
    sNowIndex.clear();
    sIndex_map.clear();
    QFile file(sMapIndexFile);
    if(!sMapIndexFile.isEmpty() && file.exists()){
        std::fstream fs(sMapIndexFile.toUtf8().constData(),std::ios_base::binary|std::ios_base::in);
        long tempLong = 0;
        long tempCount = 0;
        int tempInt = 0;
        /* read nowIndex */
        fs.read(reinterpret_cast<char *>(&tempCount),sizeof(long));
        for(long index = 0;index<tempCount;++index){
            fs.read(reinterpret_cast<char *>(&tempLong),sizeof(long));
            sNowIndex.push_back(tempLong);
        }
        /* read map vector */
        fs.read(reinterpret_cast<char *>(&tempCount),sizeof(long));
        sIndex_map.resize(tempCount);
        for(long index = 0;index<tempCount;++index){
            long mapLength = 0;
            map<vector<int>,long> tempMaps;
            fs.read(reinterpret_cast<char *>(&mapLength),sizeof(long));
            /* read each map */
            for(long mapCount = 0;mapCount<mapLength;++mapCount){
                long vecLength = 0;
                vector<int> tempVectors;
                fs.read(reinterpret_cast<char *>(&vecLength),sizeof(long));
                for(long vecCount = 0;vecCount<vecLength;++vecCount){
                    fs.read(reinterpret_cast<char *>(&tempInt),sizeof(int));
                    tempVectors.push_back(tempInt);
                }
                fs.read(reinterpret_cast<char *>(&tempLong),sizeof(long));
                tempMaps[tempVectors]=tempLong;
            }
            sIndex_map[index]=tempMaps;
        }

        fs.close();

        // print to stdout for test
//        for(unsigned long index = 0;index<sNowIndex.size();++index){
//            qDebug()<<QString("NowIndex %1th:%2").arg(index).arg(sNowIndex[index]);
//        }
//        for(unsigned vecIndex = 0;vecIndex<sIndex_map.size();++vecIndex){
//            for(map<vector<int>,long>::iterator it=sIndex_map[vecIndex].begin();it!=sIndex_map[vecIndex].end();++it){
//                QString temp=QString("%1:[").arg(vecIndex);
//                for(unsigned long index = 0;index<(it->first).size();++index){
//                    temp+=QString("%1,").arg((it->first)[index]);
//                }
//                temp+="]:";
//                temp+=QString("%1").arg(it->second);
//                qDebug()<<temp;
//            }
//        }
        return true;
    }
    return false;
}
// static function
void KCalPMK::saveMapIndex()
{
//    sNowIndex.push_back(45);
//    sNowIndex.push_back(425);
//    sNowIndex.push_back(445);
//    sNowIndex.push_back(15);
//    vector<int> a;
//    map<vector<int>,long> m;
//    a.push_back(1);
//    a.push_back(2);
//    m[a]=2323;
//    a.push_back(2);
//    m[a]=22;
//    a.push_back(56);
//    m[a]=13;
//    sIndex_map.push_back(m);
//    a.push_back(1111);
//    m[a]=111;
//    sIndex_map.push_back(m);
    if(!sMapIndexFile.isEmpty()){
        std::fstream fs(sMapIndexFile.toUtf8().constData(),std::ios_base::binary|std::ios_base::out|std::ios_base::trunc);
        long tempLong = 0;
        int tempInt = 0;
        /* write nowIndex */
        // this is the length
        tempLong = sNowIndex.size();
        fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
        // data here
        for(unsigned long index = 0;index<sNowIndex.size();++index){
            tempLong = sNowIndex[index];
            fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
        }
        /* map follows */
        // this is the length
        tempLong = sIndex_map.size();
        fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
        // data here
        for(unsigned long index = 0;index<sIndex_map.size();++index){
            // this is the length of each map
            tempLong = sIndex_map[index].size();
            fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
            // data here
            for(map<vector<int>,long>::iterator it=sIndex_map[index].begin();it!=sIndex_map[index].end();++it){
                tempLong = (it->first).size();
                fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
                for(unsigned int vecIndex = 0;vecIndex<(it->first).size();++vecIndex){
                    tempInt = (it->first)[vecIndex];
                    fs.write(reinterpret_cast<char *>(&tempInt),sizeof(int));
                }
                tempLong = it->second;
                fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
            }
        }
        fs.close();
    }
}
// make beNewInstance true if you want to ignore any mapfile to read but write only, or map will be readed from and stored into the specified file
KCalPMK::KCalPMK(QString input, QString output,bool beNewInstance,double scale)
    :m_sInput(input),
    m_sOutput(output),
    m_dScale(scale)
{
    m_PointPair.clear();

    readPrimaryHist();
    prepare();
    if(beNewInstance){
        sIndex_map.clear();
        sNowIndex.clear();
        sIndex_map.resize(m_iMaxLevel);
        sNowIndex.resize(m_iMaxLevel,0);
    }
    m_pyramid.resize(m_iMaxLevel);
    buildPyramid();
}

void KCalPMK::savePyramid_unittest()
{
    vector<map<long,long> > tempPyramid;
    std::fstream fs(m_sOutput.toUtf8().constData(),std::ios_base::binary|std::ios_base::in);
    long mapsize = 0;
    int levels = 0;
    long tempIndex = 0;
    long tempWeight = 0;

    fs.read(reinterpret_cast<char *>(&levels),sizeof(int));

    tempPyramid.resize(levels);

    // read map
    for(int index = 0;index<levels;++index){
        fs.read(reinterpret_cast<char *>(&mapsize),sizeof(long));
        for(long mapIndex=0;mapIndex<mapsize;++mapIndex){
            fs.read(reinterpret_cast<char *>(&tempIndex),sizeof(long));
            fs.read(reinterpret_cast<char *>(&tempWeight),sizeof(long));
            tempPyramid[index][tempIndex]=tempWeight;
        }
    }
    fs.close();

    // print to stdout
    for(int index = 0;index<levels;++index){
        qDebug()<<QString("level %1th total:%2").arg(index).arg(tempPyramid[index].size());
        for(map<long,long>::iterator it = tempPyramid[index].begin();
            it != tempPyramid[index].end();++it){
            QString temp("level %1th:%2-%3");
            temp=QString(temp).arg(index);
            temp=QString(temp).arg(it->first);
            temp=QString(temp).arg(it->second);
            qDebug()<<temp;
        }
    }
    qDebug()<<"levels:"<<levels;
}

void KCalPMK::savePtramid()
{
    std::fstream fs(m_sOutput.toUtf8().constData(),std::ios_base::binary|std::ios_base::out|std::ios_base::trunc);

    long tempLong = 0;

    fs.write(reinterpret_cast<char *>(&m_iMaxLevel),sizeof(int));

    //qDebug()<<"levels:"<<m_iMaxLevel;
    for(int index = 0;index<m_iMaxLevel;++index){
        tempLong = m_pyramid[index].size();
        fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
        for(map<long,long>::iterator it = m_pyramid[index].begin();
            it != m_pyramid[index].end();++it){
            tempLong = it->first;
            fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
            tempLong = it->second;
            fs.write(reinterpret_cast<char *>(&tempLong),sizeof(long));
        }
    }

    fs.close();
}

void KCalPMK::readPrimaryHist()
{
    std::fstream fs(m_sInput.toUtf8().constData(),std::ios_base::binary|std::ios_base::in);
    long tempLong = 0;
    int tempInt = 0;
    fs.read(reinterpret_cast<char *>(&m_lPointPair),sizeof(long));
    //qDebug()<<"nums:"<<m_lPointPair;

    fs.read(reinterpret_cast<char *>(&m_iDims),sizeof(int));
    //qDebug()<<"files:"<<m_iDims;

    for(long index = 0;index<m_lPointPair;++index){
        vector<int> tempVec;
        for(int dimIndex=0;dimIndex<m_iDims;++dimIndex){
            fs.read(reinterpret_cast<char *>(&tempInt),sizeof(int));
            tempVec.push_back(tempInt*m_dScale);
        }
        fs.read(reinterpret_cast<char *>(&tempLong),sizeof(long));
        m_PointPair[tempVec]=tempLong;
    }

    fs.close();
}

void KCalPMK::buildPyramid()
{
    for(int index = 0;index<m_iMaxLevel;++index){
        for(map<vector<int>,long>::iterator it = m_PointPair.begin();it!=m_PointPair.end();++it){
            vector<int> tempVec;
            long binPos=0;
            long binSize = boost::math::powm1(2,index)+1;
            for(int dimIndex=0;dimIndex<m_iDims;++dimIndex){
                int temp = it->first[dimIndex];
                int binIndex = ((temp - m_dMin)- m_transTable[index][dimIndex])*1./ binSize;
                tempVec.push_back(binIndex);
            }
            if(sIndex_map[index].find(tempVec) == sIndex_map[index].end()){
                // a new position_pair in this level are found
                binPos = sNowIndex[index]++;
                // insert this new pair
                sIndex_map[index][tempVec]=binPos;
                m_pyramid[index][binPos]=0;
            }else{
                binPos = sIndex_map[index][tempVec];
            }
            m_pyramid[index][binPos]+=it->second;
        }
    }
}

void KCalPMK::prepare()
{
    calMinMax();
    m_dDiameter = m_dMax-m_dMin+1;
    //qDebug()<<m_dDiameter;
    m_iMaxLevel = boost::math::round(boost::math::log1p(m_dDiameter-1)/boost::math::log1p(1))+1;
    //qDebug()<<m_iMaxLevel;
    m_transTable.resize(m_iMaxLevel);

    for(int index=0;index<m_iMaxLevel;++index){
        long binSize = boost::math::powm1(2,index)+1;
        boost::random::mt19937 gen(std::time(0));
        boost::random::uniform_int_distribution<> dist(0, binSize);
        m_transTable[index].resize(m_iDims,0);
        for(int dimIndex = 0;dimIndex<m_iDims;++dimIndex){
            //m_transTable[index][dimIndex] = dist(gen);
            // this trans don't work well
            m_transTable[index][dimIndex] = 0;
            //qDebug()<<QString("level:%1").arg(index)<<m_transTable[index][dimIndex];
        }
    }
}

void KCalPMK::calMinMax()
{
    m_dMin = (std::numeric_limits<int>::max)();
    m_dMax = (std::numeric_limits<int>::min)();

    for(map<vector<int>,long>::iterator it = m_PointPair.begin();it!=m_PointPair.end();++it){
        for(int nDim=0;nDim<m_iDims;++nDim){
            int temp = it->first[nDim];
            if(m_dMax<temp){
                m_dMax=temp;
            }
            if(m_dMin>temp){
                m_dMin=temp;
            }
        }
    }
}

max_stars_repo_name: PlainSailing/GraduationDesignTest

max_issues_repo_name: PlainSailing/GraduationDesignTest

max_forks_repo_name: PlainSailing/GraduationDesignTest


text:
/*
 * Copyright (c) 2020 Andreas Pohl
 * Licensed under MIT (https://github.com/apohl79/audiogridder/blob/master/COPYING)
 *
 * Author: Andreas Pohl
 */

#ifndef Client_hpp
#define Client_hpp

#include <JuceHeader.h>

#include "Message.hpp"
#include "ServerPlugin.hpp"
#include "Defaults.hpp"
#include "Utils.hpp"
#include "Metrics.hpp"
#include "ImageReader.hpp"

JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE("-Wzero-as-null-pointer-constant")
#include <boost/lockfree/spsc_queue.hpp>
JUCE_END_IGNORE_WARNINGS_GCC_LIKE

#include <memory>

namespace e47 {

class AudioGridderAudioProcessor;

template <typename T>
class AudioStreamer;

class Client : public Thread, public LogTag, public MouseListener, public KeyListener {
  public:
    static std::atomic_uint32_t count;

    Client(AudioGridderAudioProcessor* processor);
    ~Client() override;

    struct Parameter {
        int idx = -1;
        String name;
        float defaultValue = 0.0f;
        AudioProcessorParameter::Category category = AudioProcessorParameter::genericParameter;
        String label;
        int numSteps = 0x7fffffff;
        bool isBoolean = false;
        bool isDiscrete = false;
        bool isMeta = false;
        bool isOrientInv = false;
        StringArray allValues;

        int automationSlot = -1;
        float currentValue = 0.0f;

        NormalisableRange<double> range;

        static Parameter fromJson(const json& j) {
            Parameter p;
            p.idx = j["idx"].get<int>();
            p.name = j["name"].get<std::string>();
            p.defaultValue = j["defaultValue"].get<float>();
            p.category = j["category"].get<AudioProcessorParameter::Category>();
            p.label = j["label"].get<std::string>();
            p.numSteps = j["numSteps"].get<int>();
            p.isBoolean = j["isBoolean"].get<bool>();
            p.isDiscrete = j["isDiscrete"].get<bool>();
            p.isMeta = j["isMeta"].get<bool>();
            p.isOrientInv = j["isOrientInv"].get<bool>();
            String val;
            if (j.find("minValue") != j.end()) {
                val = j["minValue"].get<std::string>();
                if (val.containsOnly("0123456789-.")) {
                    p.range.start = val.getFloatValue();
                }
            }
            if (j.find("maxValue") != j.end()) {
                val = j["maxValue"].get<std::string>();
                if (val.containsOnly("0123456789-.")) {
                    p.range.end = val.getFloatValue();
                }
            }
            if (p.range.start >= p.range.end) {
                p.range.start = 0.0;
                p.range.end = 1.0;
            }
            if (j.find("allValues") != j.end()) {
                for (auto& s : j["allValues"]) {
                    p.allValues.add(s.get<std::string>());
                }
            }
            if (p.allValues.size() > 2) {
                p.range.start = 0.0f;
                p.range.end = p.allValues.size() - 1;
                p.range.interval = 1.0 / p.allValues.size();
            } else if (p.isDiscrete) {
                p.range.interval = 1.0 / p.numSteps;
                if (p.numSteps == 2) {
                    p.isBoolean = true;
                }
            }
            if (j.find("automationSlot") != j.end()) {
                p.automationSlot = j["automationSlot"].get<int>();
            }
            if (j.find("currentValue") != j.end()) {
                p.currentValue = j["currentValue"].get<float>();
            } else {
                p.currentValue = p.defaultValue;
            }
            return p;
        }

        json toJson() const {
            json j = {{"idx", idx},
                      {"name", name.toStdString()},
                      {"defaultValue", defaultValue},
                      {"currentValue", currentValue},
                      {"category", category},
                      {"label", label.toStdString()},
                      {"numSteps", numSteps},
                      {"isBoolean", isBoolean},
                      {"isDiscrete", isDiscrete},
                      {"isMeta", isMeta},
                      {"isOrientInv", isOrientInv},
                      {"minValue", String(range.start).toStdString()},
                      {"maxValue", String(range.end).toStdString()},
                      {"automationSlot", automationSlot}};
            j["allValues"] = json::array();
            for (auto& s : allValues) {
                j["allValues"].push_back(s.toStdString());
            }
            return j;
        }

        float getValue() const { return (float)range.convertFrom0to1(currentValue); }

        void setValue(float val) { currentValue = (float)range.convertTo0to1(val); }
    };

    std::atomic_int NUM_OF_BUFFERS{Defaults::DEFAULT_NUM_OF_BUFFERS};
    std::atomic_int LOAD_PLUGIN_TIMEOUT{Defaults::DEFAULT_LOAD_PLUGIN_TIMEOUT};

    void run() override;

    void setServer(const ServerInfo& srv);
    String getServerHost();
    String getServerHostAndID();
    int getServerPort();
    int getServerID();
    bool isServerLocalMode() const { return m_srvLocalMode; }
    int getChannelsIn() const { return m_channelsIn; }
    int getChannelsOut() const { return m_channelsOut; }
    double getSampleRate() const { return m_rate; }
    int getSamplesPerBlock() const { return m_samplesPerBlock; }
    int getLatencySamples() const { return m_latency + NUM_OF_BUFFERS * m_samplesPerBlock; }
    double isUsingDoublePrecission() const { return m_doublePrecission; }

    void setLatency(int i) { m_latency = i; }

    bool isReady(int timeout = 1000);
    bool isReadyLockFree();
    void init(int channelsIn, int channelsOut, int channelsSC, double rate, int samplesPerBlock, bool doublePrecission);

    void reconnect() { m_needsReconnect = true; }
    void close();

    template <typename T>
    std::shared_ptr<AudioStreamer<T>> getStreamer();

    const auto& getPlugins() const { return m_plugins; }
    Image getPluginScreen();  // create copy
    void setPluginScreen(std::shared_ptr<Image> img, int w, int h);

    using ScreenUpdateCallback = std::function<void(std::shared_ptr<Image>, int, int)>;
    void setPluginScreenUpdateCallback(ScreenUpdateCallback fn);

    using OnConnectCallback = std::function<void()>;
    void setOnConnectCallback(OnConnectCallback fn);

    using OnCloseCallback = std::function<void()>;
    void setOnCloseCallback(OnCloseCallback fn);

    bool addPlugin(String id, StringArray& presets, Array<Parameter>& params, bool& hasEditor, String settings,
                   String& err);
    void delPlugin(int idx);
    void editPlugin(int idx, int x, int y);
    void hidePlugin();
    MemoryBlock getPluginSettings(int idx);
    void setPluginSettings(int idx, String settings);
    void bypassPlugin(int idx);
    void unbypassPlugin(int idx);
    void exchangePlugins(int idxA, int idxB);
    Array<ServerPlugin> getRecents();
    void setPreset(int idx, int preset);

    float getParameterValue(int idx, int paramIdx);
    void setParameterValue(int idx, int paramIdx, float val);

    struct ParameterResult {
        int idx;
        float value;
    };

    Array<ParameterResult> getAllParameterValues(int idx, int count);

    void updateScreenCaptureArea(int val);

    void rescan(bool wipe = false);
    void restart();

    void updatePluginList(bool sendRequest = false);

    void updateCPULoad();
    float getCPULoad() const { return m_srvLoad; }

    // MouseListener
    void mouseMove(const MouseEvent& event) override;
    void mouseEnter(const MouseEvent& event) override;
    void mouseExit(const MouseEvent& /* event */) override {}
    void mouseDown(const MouseEvent& event) override;
    void mouseDrag(const MouseEvent& event) override;
    void mouseUp(const MouseEvent& event) override;
    void mouseDoubleClick(const MouseEvent& event) override;
    void mouseWheelMove(const MouseEvent& event, const MouseWheelDetails& wheel) override;

    void sendMouseEvent(MouseEvType ev, Point<float> p, bool isShiftDown, bool isCtrlDown, bool isAltDown,
                        const MouseWheelDetails* wheel = nullptr);

    // KeyListener
    bool keyPressed(const KeyPress& kp, Component* originatingComponent) override;

    void setLoadedPluginsString(const String& s) { m_loadedPluginsString = s; }
    String getLoadedPluginsString() const { return m_loadedPluginsString; }

    void setError() { m_error = true; }

  private:
    friend AudioStreamer<float>;
    friend AudioStreamer<double>;

    AudioGridderAudioProcessor* m_processor;
    String m_loadedPluginsString;
    std::mutex m_srvMtx;
    String m_srvHost = "";
    int m_srvPort = Defaults::SERVER_PORT;
    int m_srvId = 0;
    float m_srvLoad = 0.0f;
    int m_srvLoadLastUpdated = 0;
    bool m_srvLocalMode = false;
    bool m_needsReconnect = false;
    double m_rate = 0;
    bool m_doublePrecission = false;

    std::atomic_int m_channelsIn{0};
    std::atomic_int m_channelsOut{0};
    std::atomic_int m_channelsSC{0};
    std::atomic_int m_samplesPerBlock{0};
    std::atomic_int m_latency{0};

    std::atomic_bool m_ready{false};
    std::atomic_bool m_error{false};

    enum LockID {
        NOLOCK = 0,
        SETPLUGINSCREENUPDATECALLBACK,
        SETONCONNECTCALLBACK,
        SETONCLOSECALLBACK,
        INIT1,
        INIT2,
        CLOSE,
        ADDPLUGIN,
        DELPLUGIN,
        EDITPLUGIN,
        HIDEPLUGIN,
        GETPLUGINSETTINGS,
        SETPLUGINSETTINGS,
        BYPASSPLUGIN,
        UNBYPASSPLUGIN,
        EXCHANGEPLUGINS,
        GETRECENTS,
        SETPRESET,
        GETPARAMETERVALUE,
        SETPARAMETERVALUE,
        GETALLPARAMETERVALUES,
        SENDMOUSEEVENT,
        KEYPRESSED,
        UPDATESCREENCAPTUREAREA,
        RESCAN,
        RESTART,
        UPDATECPULOAD1,
        UPDATECPULOAD2,
        GETLOADEDPLUGINSSTRING,
        UPDATEPLUGINLIST
    };

    struct LockByID : public LogTagDelegate {
        Client& client;
        LockID lockid;
        bool locked = false;

        LockByID(Client& c, LockID id, bool enforce = true) : client(c), lockid(id) {
            setLogTagSource(&client);
            traceScope();
            traceln("id=" << (int)id << " enforce=" << (int)enforce);
            if (enforce) {
                lock();
                locked = true;
                traceln("locked");
            } else {
                if (tryLock()) {
                    locked = true;
                    traceln("locked");
                } else {
                    traceln("lock failed, lock aquired by id " << client.m_clientMtxId);
                }
            }
        }

        ~LockByID() {
            traceScope();
            if (locked) {
                unlock();
                traceln("unlocked id " << lockid);
            }
        }

        inline void lock() {
            client.m_clientMtx.lock();
            client.m_clientMtxId = lockid;
        }

        inline bool tryLock() {
            if (client.m_clientMtx.try_lock()) {
                client.m_clientMtxId = lockid;
                return true;
            }
            return false;
        }

        inline void unlock() {
            client.m_clientMtxId = NOLOCK;
            client.m_clientMtx.unlock();
        }
    };

    std::mutex m_clientMtx;
    LockID m_clientMtxId = NOLOCK;

    std::unique_ptr<StreamingSocket> m_cmdOut;
    std::unique_ptr<StreamingSocket> m_cmdIn;
    std::unique_ptr<StreamingSocket> m_screen_socket;
    std::vector<ServerPlugin> m_plugins;

    MessageFactory m_msgFactory;

    class ScreenReceiver : public Thread, public LogTagDelegate {
      public:
        ScreenReceiver(Client* clnt, StreamingSocket* sock) : Thread("ScreenWorker"), m_client(clnt), m_socket(sock) {
            setLogTagSource(clnt);
            traceScope();
            m_imgReader.setLogTagSource(clnt);
        }

        ~ScreenReceiver() {
            traceScope();
            signalThreadShouldExit();
            waitForThreadAndLog(m_client, this, 1000);
        }

        void run();

      private:
        Client* m_client;
        StreamingSocket* m_socket;
        std::shared_ptr<Image> m_image;
        ImageReader m_imgReader;
    };

    std::unique_ptr<ScreenReceiver> m_screenWorker;
    std::shared_ptr<Image> m_pluginScreen;
    ScreenUpdateCallback m_pluginScreenUpdateCallback;
    std::mutex m_pluginScreenMtx;

    OnConnectCallback m_onConnectCallback;
    OnCloseCallback m_onCloseCallback;

    void quit();
    void init();

    StreamingSocket* accept(StreamingSocket& sock) const;

    std::mutex m_audioMtx;
    std::shared_ptr<AudioStreamer<float>> m_audioStreamerF;
    std::shared_ptr<AudioStreamer<double>> m_audioStreamerD;

    bool audioConnectionOk();

    void handleMessage(std::shared_ptr<Message<Key>> msg);
    void handleMessage(std::shared_ptr<Message<ParameterValue>> msg);
    void handleMessage(std::shared_ptr<Message<ParameterGesture>> msg);

    ENABLE_ASYNC_FUNCTORS();
};

}  // namespace e47

#endif /* Client_hpp */


text:
#include "UI.h"
#include <string>
#include <crtdbg.h>
#include "Validator.h"

//#include <boost/regex.hpp>

using namespace std;

void UI::printMenu()
{
	cout << endl;
	cout << "Masteer C++" << endl;
	cout << "1 - Manage Tutorials repository." << endl;
	cout << "2 - Manage watchlist." << endl;
	cout << "0 - Exit." << endl;
}

void UI::printRepositoryMenu()
{
	cout << "Possible commands: " << endl;
	cout << "\t 1 - Add tutorial." << endl;
	cout << "\t 2 - Display all." << endl;
	cout << "\t 3 - Delete tutorial" << endl;
	cout << "\t 4 - Update tutorial" << endl;
	cout << "\t 5 - Filter by no. views" << endl;
	cout << "\t 0 - Back." << endl;
}

void UI::printWatchListMenu()
{
	cout << "Possible commands: " << endl;
	cout << "\t 1 - Add tutorial to watchlist" << endl;
	cout << "\t 2 - View watchlist" << endl;
	cout << "\t 3 - Delete tutorial from watchlist." << endl;
	cout << "\t 4 - Like this tutorial." << endl;
	cout << "\t 5 - Next" << endl;
	cout << "\t 6 - Display" << endl;
	cout << "\t 0 - Back." << endl;
}

void UI::addTutorialToRepo()
{
	Tutorial t;
	cout << "Enter the tutorial data(fields separated by\"'\"";

	try {
		cin >> t;
	if (this->ctrl->addTutorialToRepository(t))
		cout << "Tutorial added succesfully!" << endl;
	else
		cout << "Cannot add tutorial";
	}
	catch (RepositoryException& v){
		cout << v.what() << endl;
	}
	catch (ValidationException& v) {
		cout << v.what() << endl;
	}
}

void UI::deleteTutorialFromRepo()
{
	cout << "Enter the presenter: ";
	std::string presenter;
	getline(cin, presenter);
	cout << "Enter the title: ";
	std::string title;
	getline(cin, title);
	try {
		if (this->ctrl->removeTutorialFromRepository(presenter, title))
			cout << "The tutorial was removed successfully!";
	}
	catch (RepositoryException& r) {
		cout << r.what() << endl;
	}
}

void UI::updateTutorialFromRepo()
{
	cout << "Enter the presenter: ";
	std::string presenter;
	getline(cin, presenter);
	cout << "Enter the title: ";
	std::string title;
	getline(cin, title);
	/*cout << "Enter the new presenter: ";
	std::string newPresenter;
	getline(cin, newPresenter);
	cout << "Enter the new title: ";
	std::string newTitle;
	getline(cin, newTitle);
	std::string minutes, seconds, noLikes;
	cout << "Enter the duration: " << endl;
	cout << "\tMinutes: ";
	getline(cin, minutes);
	cout << "\tSeconds: ";
	getline(cin, seconds);
	cout << "\tNumber of likes: ";
	getline(cin, noLikes);
	cout << "Link to the tutorial: ";
	std::string link;
	getline(cin, link);*/
	cout << "Enter the new updated tutorial\n";
	Tutorial t;
	cin >> t;
	try {
	if (this->ctrl->updateTutorialFromRepository(presenter, title, t))
		cout << "Tutorial updated successfully!" << endl;
	else
		cout << "An error occured: cannot find tutorial/the new tutorial presenter and name are already added" << endl;
	}
	catch (RepositoryException& v) {
		cout << v.what() << endl;
	}
	catch (ValidationException& v) {
		cout << v.what() << endl;
	}

}

void UI::displayAllTutorialsRepo()
{
	std::vector<Tutorial>* v = this->ctrl->getRepo()->getTutorials();
	if (v->size() == 0)
	{
		cout << "There are no tutorials in the repository." << endl;
		return;
	}

	int i = 1;
	for (auto& it : *v)
	{
		cout << i << ". ";
		this->printTutorial(it, true);
		i++;
	}
}
void UI::printTutorial(const Tutorial& t, bool flag) {
	Duration d = t.getDuration();
	cout << "\tPresenter: " << t.getPresenter() << endl;
	cout << "\tTitle: " << t.getTitle() << endl;
	flag && cout << "\tNumber of likes: " << t.getNoLikes() << endl;
	cout << "\tDuration: " << d.getMinutes() << ":" << d.getSeconds() << endl;
	cout << "\tNoViews: " << t.getNoViews() << endl;
	cout << endl;
}

void UI::addTutorialToWatchlist()
{
	try {
		this->ctrl->addTutorialToWatchlist(this->ctrl->getCurrentTutorial());
	}
	catch (RepositoryException& v) {
		cout << "Tutorial already added to watchlist"<<endl;
	}
}

void UI::viewWatchlist()
{
	std::vector<Tutorial>* v = this->ctrl->getWatchlist()->getTutorials();
	if (v->size() == 0)
	{
		cout << "There are no tutorials in the watchlist." << endl;
		return;
	}
	int i = 0;
	for (auto& it : *v)
	{
		cout << i << ". ";
		this->printTutorial(it, false);
		i++;

	}
}

UI::UI(Controller * c)
{
	ctrl = c;
}

UI::~UI()
{
	delete ctrl;
}

void UI::run()
{
	while (true)
	{
		UI::printMenu();
		int command{ 0 };
		std::string comm;
		cout << "Input the command: ";
		getline(cin, comm);
		try {
			command = Validator::strToInt(comm);
		}
		catch (ValidationException& v) {
			cout << "Command error: " << v.what();
			continue;
		}
		if (command == 0)
			break;

		// repository management
		if (command == 1)
		{
			while (true)
			{
				UI::printRepositoryMenu();
				int commandRepo{ 0 };
				std::string comm;
				cout << "Input the command: ";
				getline(cin, comm);
				try {
					commandRepo = Validator::strToInt(comm);
				}
				catch (ValidationException& v) {
					cout << "Command error: " << v.what();
				}

				if (commandRepo == 0)
					break;
				switch (commandRepo)
				{
				case 1:
					this->addTutorialToRepo();
					break;
				case 2:
					this->displayAllTutorialsRepo();
					break;
				case 3:
					this->deleteTutorialFromRepo();
					break;
				case 4:
					this->updateTutorialFromRepo();
					break;
				case 5:
					int value;
					cout << "Please give number: ";
					cin >> value;
					std::vector<Tutorial> v = this->ctrl->filter(value);
					for (auto& it : v) {
						printTutorial(it);
					}
					break;
				}
			}
		}

		// watchlist management
		if (command == 2)
		{
			std::string presenter{};
			cout << "What presenter would you like to watch?";
			getline(cin, presenter);
			this->ctrl->configIterator(presenter);
				if (this->ctrl->getCurrentTutorial().getPresenter() != "")
				{
					this->ctrl->startIteration();
					printTutorial(this->ctrl->getCurrentTutorial(), false);
				}
				else {
					cout << "Sorry no tutorial with that presenter exists" << endl;
					continue;
				}
			cout << endl;
			while (true)
			{
				UI::printWatchListMenu();
				int commandPlaylist{ 0 };
				std::string comm;
				cout << "Input the command: ";
				getline(cin, comm);
				try {
					commandPlaylist = Validator::strToInt(comm);
				}
				catch (ValidationException& v) {
					cout << "Command error: " << v.what();
				}
				if (commandPlaylist == 0)
					break;
				switch (commandPlaylist)
				{
				case 1:
					this->addTutorialToWatchlist();
					break;
				case 2:
					this->viewWatchlist();
					break;
				case 3:
				{
					try {

					if (this->ctrl->deleteTutorialFromWatchlist(this->ctrl->getCurrentTutorial()))
						cout << "Tutorial deleted from watchlist" << endl;
					else
						cout << "Tutorial is not in playlist" << endl;
					break;
					}
					catch (RepositoryException& v) {
						cout << "The tutorial is not in playlist" << endl;
					}
				}
				case 5:
				{
					this->ctrl->next();
					this->printTutorial(this->ctrl->getCurrentTutorial(), false);
					break;
				}
				case 4: {
					this->ctrl->likeTutorial();
					break;
				}
				case 6: {
					this->ctrl->display();
					break;
				}
				}
			}
		}
	}
}

max_stars_repo_path: Laboratory5(Week 10-12)/Lab8-9 - Without Qt Designer/Lab8-9GUI/UI.cpp


text:
/*
 * @CopyRight:
 * FISCO-BCOS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FISCO-BCOS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FISCO-BCOS.  If not, see <http://www.gnu.org/licenses/>
 * (c) 2016-2018 fisco-dev contributors.
 */

#include "Common.h"
#include <libstorage/StorageException.h>
#include <libstorage/Table.h>
#include <boost/test/unit_test.hpp>

using namespace dev;
using namespace dev::storage;

namespace test_Storage
{
struct StorageFixture
{
    StorageFixture()
    {
        entry = std::make_shared<Entry>();
        entries = std::make_shared<Entries>();
        condition = std::make_shared<Condition>();
    }

    ~StorageFixture() {}

    dev::storage::Entry::Ptr entry;
    dev::storage::Entries::Ptr entries;
    dev::storage::Condition::Ptr condition;
    dev::storage::Table::Ptr stateDB;
};

BOOST_FIXTURE_TEST_SUITE(Storage, StorageFixture)

BOOST_AUTO_TEST_CASE(entryTest)
{
    entry->setStatus(1);
    BOOST_TEST_TRUE(entry->getStatus() == 1u);

    BOOST_TEST_TRUE(entry->dirty() == true);

    entry->setField("key", "value");
    BOOST_TEST_TRUE(entry->getField("key") == "value");

    BOOST_TEST_TRUE(entry->dirty() == true);

    entry->setDirty(false);
    BOOST_TEST_TRUE(entry->dirty() == false);
}

BOOST_AUTO_TEST_CASE(entriesTest)
{
    BOOST_TEST_TRUE(entries->size() == 0u);
    BOOST_TEST_TRUE(entries->dirty() == false);

    entries->addEntry(entry);

    BOOST_TEST_TRUE(entries->size() == 1u);
    BOOST_TEST_TRUE(entries->get(0) == entry);
    BOOST_CHECK_THROW(entries->get(5), dev::storage::StorageException);
    BOOST_TEST_TRUE(entries->dirty() == true);
}

BOOST_AUTO_TEST_CASE(conditionTest)
{
    condition->limit(1);
    BOOST_TEST_TRUE(condition->empty());
}

BOOST_AUTO_TEST_CASE(StateExceptionTest)
{
    StorageException storageException{1, "error"};
    BOOST_TEST_TRUE(storageException.errorCode() == 1);
}

BOOST_AUTO_TEST_SUITE_END()

}  // namespace test_Storage

max_stars_repo_name: imtypist/FISCO-BCOS

max_issues_repo_name: imtypist/FISCO-BCOS

max_forks_repo_name: imtypist/FISCO-BCOS