<commit_before>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Julian Ganz
 *
 * 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.
 */
#ifndef CMOH_STRING_VIEW_HPP__
#define CMOH_STRING_VIEW_HPP__

// We try to detect whether a standard `string_view` is available, but only for
// post-C++14 (we don't expect a C++14 STL to ship it). We don't consider the
// `experimental/string_view` header, since at least one implementation (the one
// shipped with GCC), lacks `constexpr` in critical places.
#if __cplusplus > 201402L
# if __has_include(<string_view>)
#  define has_string_view 1
# endif
#endif

// local includes
#include <cmoh/char_traits.hpp>

// use one of the `string_view` implementations
#ifdef has_string_view
#include <string_view>
namespace cmoh {
    template <
        typename CharT,
        typename Traits = char_traits<CharT>
    >
    using basic_string_view = std::basic_string_view<CharT, Traits>;
}
#else

// std includes
#include <algorithm>
#include <cstddef>
#include <limits>
#include <ostream>
#include <stdexcept>

namespace cmoh {

/**
 * Predefinition of the C++17 std::basic_string_view type
 *
 * This template provides an optional type which is modeled after the
 * std::basic_string_view which is part of the C++17 standard proposal. Note
 * that only a subset of the interface is provided. Also note that the Traits
 * defaults to a custom `char_traits`, which has some additional compile
 * capabilities but is somewhat slow at run time.
 *
 * For documentation, refer to the C++17 proposal or your favorite STL
 * documentation site.
 */
template <
    typename CharT,
    typename Traits = char_traits<CharT>
>
class basic_string_view {
public:
    typedef Traits traits_type;

    // value types
    typedef CharT value_type;
    typedef CharT* pointer;
    typedef CharT const* const_pointer;
    typedef CharT& reference;
    typedef CharT const& const_reference;

    // TODO: iterator types

    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

    constexpr basic_string_view() noexcept : _data(nullptr), _count(0) {}
    constexpr basic_string_view(const basic_string_view& other) noexcept =
        default;
    constexpr basic_string_view(const CharT* data, size_type count) noexcept :
        _data(data), _count(count) {}
    constexpr basic_string_view(const CharT* data) :
        _data(data), _count(traits_type::length(data)) {}

    basic_string_view& operator=( const basic_string_view& view ) = default;

    // TODO: iterators

    constexpr const_reference operator[](size_type pos) const {
        return _data[pos];
    }

    constexpr const_reference at(size_type pos) const {
        if (pos >= size())
            throw std::out_of_range("Access out-of-bounds element.");
        return _data[pos];
    }

    constexpr const_reference front() const {
        return _data[0];
    }

    constexpr const_reference back() const {
        return _data[size() - 1];
    }

    constexpr const_pointer data() const noexcept {
        return _data;
    }

    constexpr size_type size() const noexcept {
        return _count;
    }

    constexpr size_type length() const noexcept {
        return size();
    }

    constexpr size_type max_size() const noexcept {
        return std::numeric_limits<size_type>::max();
    }

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

    constexpr void remove_prefix(size_type n) {
        _data+=n;
        _count-=n;
    }

    constexpr void remove_suffix(size_type n) {
        _count-=n;
    }

    constexpr void swap(basic_string_view& v) {
        const_pointer* data = v._data;
        size_type count = v._count;

        v._data = _data;
        v._count = _count;

        _data = data;
        _count = count;
    }

    size_type copy(CharT* dest, size_type count, size_type pos = 0) const {
        if (pos >= size())
            throw std::out_of_range("Access out-of-bounds element.");
        count = std::min(count, size() - pos);
        traits_type::copy(
            dest,
            &_data[pos],
            count*sizeof(value_type)/sizeof(char)
        );
        return count;
    }

    constexpr basic_string_view
    substr(size_type pos = 0, size_type count = npos) const {
        if (pos >= size())
            throw std::out_of_range("Access out-of-bounds element.");
        return basic_string_view(_data + pos, std::min(count, size() - pos));
    }

    constexpr int compare(basic_string_view v) const noexcept {
        auto retval = traits_type::compare(
            data(),
            v.data(),
            std::min(size(), v.size())
        );
        if (retval != 0)
            return retval;
        if (size() == v.size())
            return 0;
        return size() < v.size() ? -1 : 1;
    }

    constexpr int
    compare(size_type pos1, size_type count1, basic_string_view v) const {
        return substr(pos1, count1).compare(v);
    }

    constexpr int
    compare(
        size_type pos1,
        size_type count1,
        basic_string_view v,
        size_type pos2,
        size_type count2
    ) const {
        return substr(pos1, count1).compare(v.substr(pos2, count2));
    }

    constexpr int compare(const_pointer s) const {
        return compare(basic_string_view(s));
    }

    constexpr int
    compare(size_type pos1, size_type count1, const_pointer s) const {
        return substr(pos1, count1).compare(s);
    }

    constexpr int
    compare(
        size_type pos1,
        size_type count1,
        const_pointer s,
        size_type count2
    ) const {
        return substr(pos1, count1).compare(basic_string_view(s, count2));
    }

    // TODO: find, rfind, ...

    static constexpr size_type npos = size_type(-1);

private:
    value_type const* _data;
    size_type _count;
};

}

template<
    class CharT,
    class Traits
>
constexpr bool operator == (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) == 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator != (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) != 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator < (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) < 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator <= (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) <= 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator > (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) > 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator >= (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) >= 0;
}

template <
    class CharT,
    class Traits
>
std::basic_ostream<CharT, Traits>&
operator << (
    std::basic_ostream<CharT, Traits>& stream,
    cmoh::basic_string_view<CharT, Traits> view
) {
    auto len = view.size();
    auto pos = view.data();

    while (len > 0) {
        stream.put(*pos);
        ++pos;
        --len;
    }

    return stream;
}

// TODO: hash

#endif

namespace cmoh {

typedef basic_string_view<char> string_view;
typedef basic_string_view<wchar_t> wstring_view;
typedef basic_string_view<char16_t> u16string_view;
typedef basic_string_view<char32_t> u32string_view;

/**
 * Create a string view with the standard char traits
 */
template <
    typename CharT,
    typename Traits
>
constexpr
basic_string_view<CharT, std::char_traits<CharT>>
std_traits_using(
    basic_string_view<CharT, Traits> const& view
) {
    return basic_string_view<CharT, std::char_traits<CharT>>(
        view.data(),
        view.size()
    );
}

/**
 * Create a string view with the cmoh char traits
 */
template <
    typename CharT,
    typename Traits
>
constexpr
basic_string_view<CharT>
cmoh_traits_using(
    basic_string_view<CharT, Traits> const& view
) {
    return basic_string_view<CharT>(view.data(), view.size());
}

}

// workaround to interface our custom char traits with the outside world
template <
    class CharT
>
std::basic_ostream<CharT, std::char_traits<CharT>>&
operator << (
    std::basic_ostream<CharT>& stream,
    cmoh::basic_string_view<CharT> view
) {
    return stream << std_traits_using(view);
}

#endif
<commit_msg>Add more workaround operators to interface traits<commit_after>/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Julian Ganz
 *
 * 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.
 */
#ifndef CMOH_STRING_VIEW_HPP__
#define CMOH_STRING_VIEW_HPP__

// We try to detect whether a standard `string_view` is available, but only for
// post-C++14 (we don't expect a C++14 STL to ship it). We don't consider the
// `experimental/string_view` header, since at least one implementation (the one
// shipped with GCC), lacks `constexpr` in critical places.
#if __cplusplus > 201402L
# if __has_include(<string_view>)
#  define has_string_view 1
# endif
#endif

// local includes
#include <cmoh/char_traits.hpp>

// use one of the `string_view` implementations
#ifdef has_string_view
#include <string_view>
namespace cmoh {
    template <
        typename CharT,
        typename Traits = char_traits<CharT>
    >
    using basic_string_view = std::basic_string_view<CharT, Traits>;
}
#else

// std includes
#include <algorithm>
#include <cstddef>
#include <limits>
#include <ostream>
#include <stdexcept>

namespace cmoh {

/**
 * Predefinition of the C++17 std::basic_string_view type
 *
 * This template provides an optional type which is modeled after the
 * std::basic_string_view which is part of the C++17 standard proposal. Note
 * that only a subset of the interface is provided. Also note that the Traits
 * defaults to a custom `char_traits`, which has some additional compile
 * capabilities but is somewhat slow at run time.
 *
 * For documentation, refer to the C++17 proposal or your favorite STL
 * documentation site.
 */
template <
    typename CharT,
    typename Traits = char_traits<CharT>
>
class basic_string_view {
public:
    typedef Traits traits_type;

    // value types
    typedef CharT value_type;
    typedef CharT* pointer;
    typedef CharT const* const_pointer;
    typedef CharT& reference;
    typedef CharT const& const_reference;

    // TODO: iterator types

    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;

    constexpr basic_string_view() noexcept : _data(nullptr), _count(0) {}
    constexpr basic_string_view(const basic_string_view& other) noexcept =
        default;
    constexpr basic_string_view(const CharT* data, size_type count) noexcept :
        _data(data), _count(count) {}
    constexpr basic_string_view(const CharT* data) :
        _data(data), _count(traits_type::length(data)) {}

    basic_string_view& operator=( const basic_string_view& view ) = default;

    // TODO: iterators

    constexpr const_reference operator[](size_type pos) const {
        return _data[pos];
    }

    constexpr const_reference at(size_type pos) const {
        if (pos >= size())
            throw std::out_of_range("Access out-of-bounds element.");
        return _data[pos];
    }

    constexpr const_reference front() const {
        return _data[0];
    }

    constexpr const_reference back() const {
        return _data[size() - 1];
    }

    constexpr const_pointer data() const noexcept {
        return _data;
    }

    constexpr size_type size() const noexcept {
        return _count;
    }

    constexpr size_type length() const noexcept {
        return size();
    }

    constexpr size_type max_size() const noexcept {
        return std::numeric_limits<size_type>::max();
    }

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

    constexpr void remove_prefix(size_type n) {
        _data+=n;
        _count-=n;
    }

    constexpr void remove_suffix(size_type n) {
        _count-=n;
    }

    constexpr void swap(basic_string_view& v) {
        const_pointer* data = v._data;
        size_type count = v._count;

        v._data = _data;
        v._count = _count;

        _data = data;
        _count = count;
    }

    size_type copy(CharT* dest, size_type count, size_type pos = 0) const {
        if (pos >= size())
            throw std::out_of_range("Access out-of-bounds element.");
        count = std::min(count, size() - pos);
        traits_type::copy(
            dest,
            &_data[pos],
            count*sizeof(value_type)/sizeof(char)
        );
        return count;
    }

    constexpr basic_string_view
    substr(size_type pos = 0, size_type count = npos) const {
        if (pos >= size())
            throw std::out_of_range("Access out-of-bounds element.");
        return basic_string_view(_data + pos, std::min(count, size() - pos));
    }

    constexpr int compare(basic_string_view v) const noexcept {
        auto retval = traits_type::compare(
            data(),
            v.data(),
            std::min(size(), v.size())
        );
        if (retval != 0)
            return retval;
        if (size() == v.size())
            return 0;
        return size() < v.size() ? -1 : 1;
    }

    constexpr int
    compare(size_type pos1, size_type count1, basic_string_view v) const {
        return substr(pos1, count1).compare(v);
    }

    constexpr int
    compare(
        size_type pos1,
        size_type count1,
        basic_string_view v,
        size_type pos2,
        size_type count2
    ) const {
        return substr(pos1, count1).compare(v.substr(pos2, count2));
    }

    constexpr int compare(const_pointer s) const {
        return compare(basic_string_view(s));
    }

    constexpr int
    compare(size_type pos1, size_type count1, const_pointer s) const {
        return substr(pos1, count1).compare(s);
    }

    constexpr int
    compare(
        size_type pos1,
        size_type count1,
        const_pointer s,
        size_type count2
    ) const {
        return substr(pos1, count1).compare(basic_string_view(s, count2));
    }

    // TODO: find, rfind, ...

    static constexpr size_type npos = size_type(-1);

private:
    value_type const* _data;
    size_type _count;
};

}

template<
    class CharT,
    class Traits
>
constexpr bool operator == (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) == 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator != (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) != 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator < (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) < 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator <= (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) <= 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator > (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) > 0;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator >= (
    cmoh::basic_string_view<CharT,Traits> lhs,
    cmoh::basic_string_view<CharT,Traits> rhs
) noexcept {
    return lhs.compare(rhs) >= 0;
}

template <
    class CharT,
    class Traits
>
std::basic_ostream<CharT, Traits>&
operator << (
    std::basic_ostream<CharT, Traits>& stream,
    cmoh::basic_string_view<CharT, Traits> view
) {
    auto len = view.size();
    auto pos = view.data();

    while (len > 0) {
        stream.put(*pos);
        ++pos;
        --len;
    }

    return stream;
}

// TODO: hash

#endif

namespace cmoh {

typedef basic_string_view<char> string_view;
typedef basic_string_view<wchar_t> wstring_view;
typedef basic_string_view<char16_t> u16string_view;
typedef basic_string_view<char32_t> u32string_view;

/**
 * Create a string view with the standard char traits
 */
template <
    typename CharT,
    typename Traits
>
constexpr
basic_string_view<CharT, std::char_traits<CharT>>
std_traits_using(
    basic_string_view<CharT, Traits> const& view
) {
    return basic_string_view<CharT, std::char_traits<CharT>>(
        view.data(),
        view.size()
    );
}

/**
 * Create a string view with the cmoh char traits
 */
template <
    typename CharT,
    typename Traits
>
constexpr
basic_string_view<CharT>
cmoh_traits_using(
    basic_string_view<CharT, Traits> const& view
) {
    return basic_string_view<CharT>(view.data(), view.size());
}

}

// workarounds to interface our custom char traits with the outside world
template<
    class CharT
>
constexpr bool operator == (
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> rhs
) noexcept {
    return lhs == cmoh_traits_using(rhs);
}

template<
    class CharT
>
constexpr bool operator == (
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> rhs
) noexcept {
    return cmoh_traits_using(lhs) == rhs;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator != (
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> rhs
) noexcept {
    return lhs != cmoh_traits_using(rhs);
}

template<
    class CharT
>
constexpr bool operator != (
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> rhs
) noexcept {
    return cmoh_traits_using(lhs) != rhs;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator < (
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> rhs
) noexcept {
    return lhs < cmoh_traits_using(rhs);
}

template<
    class CharT
>
constexpr bool operator < (
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> rhs
) noexcept {
    return cmoh_traits_using(lhs) < rhs;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator <= (
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> rhs
) noexcept {
    return lhs <= cmoh_traits_using(rhs);
}

template<
    class CharT
>
constexpr bool operator <= (
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> rhs
) noexcept {
    return cmoh_traits_using(lhs) <= rhs;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator > (
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> rhs
) noexcept {
    return lhs > cmoh_traits_using(rhs);
}

template<
    class CharT
>
constexpr bool operator > (
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> rhs
) noexcept {
    return cmoh_traits_using(lhs) > rhs;
}

template<
    class CharT,
    class Traits
>
constexpr bool operator >= (
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> rhs
) noexcept {
    return lhs >= cmoh_traits_using(rhs);
}

template<
    class CharT
>
constexpr bool operator >= (
    cmoh::basic_string_view<CharT,  std::char_traits<CharT>> lhs,
    cmoh::basic_string_view<CharT, cmoh::char_traits<CharT>> rhs
) noexcept {
    return cmoh_traits_using(lhs) >= rhs;
}

template <
    class CharT
>
std::basic_ostream<CharT, std::char_traits<CharT>>&
operator << (
    std::basic_ostream<CharT>& stream,
    cmoh::basic_string_view<CharT> view
) {
    return stream << std_traits_using(view);
}

#endif
<|endoftext|>


<commit_before>#pragma once

#include <future>
#include <chrono>
#include <string>
#include <cstdint>

#include <curlpp/cURLpp.hpp>
#include <curlpp/Easy.hpp>
#include <curlpp/Options.hpp>

namespace wonder_rabbit_project
{
  namespace wonderland
  {
    namespace loader
    {
      using buffer_t = std::vector<std::uint8_t>;
      using future_t = std::future<buffer_t>;

      // main feature: load data from url with async/future
      template < class T = void >
      auto load(const std::string& url)
        -> future_t
      {
        return std::async
        ( std::launch::async
        , [ url ]
          {
            // temporary buffer
            buffer_t buffer;

            cURLpp::Cleanup cleaner;
            cURLpp::Easy request;
            request.setOpt( new cURLpp::Options::Url(url) );
            request.setOpt
            ( new cURLpp::Options::WriteFunction
              ( cURLpp::Types::WriteFunctionFunctor
                ( [ &buffer ] (char* p, std::size_t size, std::size_t blocks)
                  {
                    const auto total_size = size * blocks;
                    std::copy( p, p + total_size, std::back_inserter(buffer) );
                    return total_size;
                  }
                )
              )
            );

            // it is blocking proccess!
            request.perform();

            return buffer;
          }
        );
      }

    }
  }
}
<commit_msg>実装を libcurl&libcurlpp から libPoco へ変更<commit_after>#pragma once

#include <future>
#include <chrono>
#include <string>
#include <cstdint>

#include <Poco/Net/HTTPClientSession.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/URI.h>
#include <Poco/Exception.h>

namespace wonder_rabbit_project
{
  namespace wonderland
  {
    namespace loader
    {
      using buffer_t = std::vector<std::uint8_t>;
      using future_t = std::future<buffer_t>;

      // main feature: load data from url with async/future
      template < class T = void >
      auto load(const std::string& url)
        -> future_t
      {
        return std::async
        ( std::launch::async
        , [ url ]
          {
            // temporary buffer
            buffer_t buffer;

            try
            {

              Poco::URI uri( url );

              Poco::Net::HTTPClientSession session( uri.getHost(), uri.getPort() );

              const auto path = uri.getPathAndQuery();
              Poco::Net::HTTPRequest request( Poco::Net::HTTPRequest::HTTP_GET, path.empty() ? "/" : path, Poco::Net::HTTPMessage::HTTP_1_1 );

              session.sendRequest( request );

              Poco::Net::HTTPResponse response;

              if ( response.getStatus() != Poco::Net::HTTPResponse::HTTPStatus::HTTP_OK )
                return buffer;

              auto& bin = session.receiveResponse( response );
              std::copy( std::istreambuf_iterator< char >( bin ), std::istreambuf_iterator< char >(), std::back_inserter( buffer ) );
            }
            catch( const Poco::Exception& e )
            {
              std::cerr << "== Poco Exception ==> " << e.what();
              throw e;
            }

            return buffer;
          }
        );
      }

    }
  }
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// 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.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <iostream>
#include <Context.h>
#include <Filter.h>
#include <text.h>
#include <util.h>
#include <i18n.h>
#include <main.h>
#include <CmdDuplicate.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdDuplicate::CmdDuplicate ()
{
  _keyword     = "duplicate";
  _usage       = "task <filter> duplicate <mods>";
  _description = STRING_CMD_DUPLICATE_USAGE;
  _read_only   = false;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdDuplicate::execute (std::string& output)
{
  int rc = 0;
  int count = 0;

  // Apply filter.
  Filter filter;
  std::vector <Task> filtered;
  filter.subset (filtered);
  if (filtered.size () == 0)
  {
    context.footnote (STRING_FEEDBACK_NO_TASKS_SP);
    return 1;
  }

  // Apply the command line modifications to the new task.
  A3 modifications = context.a3.extract_modifications ();

  // Accumulated project change notifications.
  std::map <std::string, std::string> projectChanges;

  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    // Duplicate the specified task.
    Task dup (*task);
    dup.set ("uuid", uuid ());     // Needs a new UUID.
    dup.remove ("start");          // Does not inherit start date.
    dup.remove ("end");            // Does not inherit end date.
    dup.remove ("entry");          // Does not inherit entry date.

    // When duplicating a child task, downgrade it to a plain task.
    if (dup.has ("parent"))
    {
      dup.remove ("parent");
      dup.remove ("recur");
      dup.remove ("until");
      dup.remove ("imask");

      std::cout << format (STRING_CMD_DUPLICATE_NON_REC, task->id)
          << "\n";
    }

    // When duplicating a parent task, create a new parent task.
    else if (dup.getStatus () == Task::recurring)
    {
      dup.remove ("mask");

      std::cout << format (STRING_CMD_DUPLICATE_REC, task->id)
          << "\n";
    }

    dup.setStatus (Task::pending); // Does not inherit status.
                                   // Must occur after Task::recurring check.

    modify_task_annotate (dup, modifications);

    if (permission (dup,
                    format (STRING_CMD_DUPLICATE_CONFIRM,
                            task->id,
                            task->get ("description")),
                    filtered.size ()))
    {
      context.tdb2.add (dup);
      ++count;
      feedback_affected (STRING_CMD_DUPLICATE_TASK, *task);

      if (context.verbose ("new-id"))
        std::cout << format (STRING_CMD_ADD_FEEDBACK, context.tdb2.next_id ()) + "\n";

      if (context.verbose ("project"))
        projectChanges[task->get ("project")] = onProjectChange (*task);
    }
    else
    {
      std::cout << STRING_CMD_DUPLICATE_NO << "\n";
      rc = 1;
      if (_permission_quit)
        break;
    }
  }

  // Now list the project changes.
  std::map <std::string, std::string>::iterator i;
  for (i = projectChanges.begin (); i != projectChanges.end (); ++i)
    if (i->first != "")
      context.footnote (i->second);

  context.tdb2.commit ();
  feedback_affected (count == 1 ? STRING_CMD_DUPLICATE_1 : STRING_CMD_DUPLICATE_N, count);
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>CmdDuplicate<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2006 - 2014, Paul Beckingham, Federico Hernandez.
//
// 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.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <iostream>
#include <Context.h>
#include <Filter.h>
#include <text.h>
#include <util.h>
#include <i18n.h>
#include <main.h>
#include <CmdDuplicate.h>

extern Context context;

////////////////////////////////////////////////////////////////////////////////
CmdDuplicate::CmdDuplicate ()
{
  _keyword     = "duplicate";
  _usage       = "task <filter> duplicate <mods>";
  _description = STRING_CMD_DUPLICATE_USAGE;
  _read_only   = false;
  _displays_id = false;
}

////////////////////////////////////////////////////////////////////////////////
int CmdDuplicate::execute (std::string& output)
{
  int rc = 0;
  int count = 0;

  // Apply filter.
  Filter filter;
  std::vector <Task> filtered;
  filter.subset (filtered);
  if (filtered.size () == 0)
  {
    context.footnote (STRING_FEEDBACK_NO_TASKS_SP);
    return 1;
  }

  // Accumulated project change notifications.
  std::map <std::string, std::string> projectChanges;

  std::vector <Task>::iterator task;
  for (task = filtered.begin (); task != filtered.end (); ++task)
  {
    // Duplicate the specified task.
    Task dup (*task);
    dup.set ("uuid", uuid ());     // Needs a new UUID.
    dup.remove ("start");          // Does not inherit start date.
    dup.remove ("end");            // Does not inherit end date.
    dup.remove ("entry");          // Does not inherit entry date.

    // When duplicating a child task, downgrade it to a plain task.
    if (dup.has ("parent"))
    {
      dup.remove ("parent");
      dup.remove ("recur");
      dup.remove ("until");
      dup.remove ("imask");

      std::cout << format (STRING_CMD_DUPLICATE_NON_REC, task->id)
          << "\n";
    }

    // When duplicating a parent task, create a new parent task.
    else if (dup.getStatus () == Task::recurring)
    {
      dup.remove ("mask");

      std::cout << format (STRING_CMD_DUPLICATE_REC, task->id)
          << "\n";
    }

    dup.setStatus (Task::pending); // Does not inherit status.
                                   // Must occur after Task::recurring check.

    dup.modify (Task::modAnnotate);

    if (permission (dup,
                    format (STRING_CMD_DUPLICATE_CONFIRM,
                            task->id,
                            task->get ("description")),
                    filtered.size ()))
    {
      context.tdb2.add (dup);
      ++count;
      feedback_affected (STRING_CMD_DUPLICATE_TASK, *task);

      if (context.verbose ("new-id"))
        std::cout << format (STRING_CMD_ADD_FEEDBACK, context.tdb2.next_id ()) + "\n";

      if (context.verbose ("project"))
        projectChanges[task->get ("project")] = onProjectChange (*task);
    }
    else
    {
      std::cout << STRING_CMD_DUPLICATE_NO << "\n";
      rc = 1;
      if (_permission_quit)
        break;
    }
  }

  // Now list the project changes.
  std::map <std::string, std::string>::iterator i;
  for (i = projectChanges.begin (); i != projectChanges.end (); ++i)
    if (i->first != "")
      context.footnote (i->second);

  context.tdb2.commit ();
  feedback_affected (count == 1 ? STRING_CMD_DUPLICATE_1 : STRING_CMD_DUPLICATE_N, count);
  return rc;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#pragma once
/**
	@file
	@brief bit vector
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <cybozu/exception.hpp>
#include <algorithm>
#include <vector>
#include <assert.h>

namespace cybozu {

template<class T>
size_t RoundupBit(size_t bitLen)
{
	const size_t unitSize = sizeof(T) * 8;
	return (bitLen + unitSize - 1) / unitSize;
}

template<class T>
T GetMaskBit(size_t bitLen)
{
	assert(bitLen < sizeof(T) * 8);
	return (T(1) << bitLen) - 1;
}

template<class T>
void SetBlockBit(T *buf, size_t bitLen)
{
	const size_t unitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitSize;
	const size_t r = bitLen % unitSize;
	buf[q] |= T(1) << r;
}
template<class T>
void ResetBlockBit(T *buf, size_t bitLen)
{
	const size_t unitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitSize;
	const size_t r = bitLen % unitSize;
	buf[q] &= ~(T(1) << r);
}
template<class T>
bool GetBlockBit(const T *buf, size_t bitLen)
{
	const size_t unitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitSize;
	const size_t r = bitLen % unitSize;
	return (buf[q] & (T(1) << r)) != 0;
}

template<class T>
void CopyBit(T* dst, const T* src, size_t bitLen)
{
	const size_t unitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitSize;
	const size_t r = bitLen % unitSize;
	for (size_t i = 0; i < q; i++) dst[i] = src[i];
	if (r == 0) return;
	dst[q] = src[q] & GetMaskBit<T>(r);
}
/*
	dst[] = (src[] << shift) | ext
	@param dst [out] dst[0..bitLen)
	@param src [in] src[0..bitLen)
	@param bitLen [in] length of src, dst
	@param shift [in] 0 <= shift < unitSize
	@param ext [in] or bit
*/
template<class T>
T ShiftLeftBit(T* dst, const T* src, size_t bitLen, size_t shift, T ext = 0)
{
	if (bitLen == 0) return 0;
	const size_t unitSize = sizeof(T) * 8;
	if (shift >= unitSize) {
		throw cybozu::Exception("ShiftLeftBit:large shift") << shift;
	}
	const size_t n = RoundupBit<T>(bitLen); // n >= 1 because bitLen > 0
	const size_t r = bitLen % unitSize;
	const T mask = r > 0 ? GetMaskBit<T>(r) : T(-1);
	if (shift == 0) {
		if (n == 1) {
			dst[0] = (src[0] & mask) | ext;
		} else {
			dst[n - 1] = src[n - 1] & mask;
			for (size_t i = n - 2; i > 0; i--) {
				dst[i] = src[i];
			}
			dst[0] = src[0] | ext;
		}
		return 0;
	}
	const size_t revShift = unitSize - shift;
	T prev = src[n - 1] & mask;
	const T ret = prev >> revShift;
	for (size_t i = n - 1; i > 0; i--) {
		T v = src[i - 1];
		dst[i] = (prev << shift) | (v >> revShift);
		prev = v;
	}
	dst[0] = (prev << shift) | ext;
	return ret;
}

namespace bitvector_local {

/*
	dst[] = src[] << shift
	dst[0..shift) does not change

	@param dst [out] dst[shift..bitLen + shift)
	@param src [in] src[0..bitLen)
	@param bitLen [in] read bit size
	@param shift [in] 0 <= shift < unitSize
*/
template<class T>
void shiftLeftBit(T* dst, const T* src, size_t bitLen, size_t shift)
{
	const size_t unitSize = sizeof(T) * 8;

	assert(bitLen);
	assert(0 < shift && shift < unitSize);

	const size_t dstN = RoundupBit<T>(bitLen + shift);
	const size_t srcN = RoundupBit<T>(bitLen);
	const size_t r = bitLen % unitSize;
	const T mask = r ? GetMaskBit<T>(r) : T(-1);
	const size_t revShift = unitSize - shift;

	T prev = src[srcN - 1] & mask;
	if (dstN > srcN) {
		dst[dstN - 1] = prev >> revShift;
	}
	for (size_t i = srcN - 1; i > 0; i--) {
		T v = src[i - 1];
		dst[i] = (prev << shift) | (v >> revShift);
		prev = v;
	}
	T ext = dst[0] & GetMaskBit<T>(shift);
	dst[0] = (prev << shift) | ext;
}

/*
	dst[] = src[] >> shift

	@param dst [out] dst[0..bitLen)
	@param src [in] src[shift..bitLen + shift)
	@param bitLen [in] write bit size
	@param shift [in] 0 <= shift < unitSize
	@note src[bitLen + shift - 1] is accessable
*/
template<class T>
void shiftRightBit(T* dst, const T* src, size_t bitLen, size_t shift)
{
	const size_t unitSize = sizeof(T) * 8;

	assert(bitLen);
	assert(0 < shift && shift < unitSize);

	const size_t dstN = RoundupBit<T>(bitLen);
	const size_t srcN = RoundupBit<T>(bitLen + shift);// srcN = dstN, dstN + 1
	const size_t r = (bitLen + shift) % unitSize;
	const T mask = r ? GetMaskBit<T>(r) : T(-1);
	if (srcN == 1) {
		dst[0] = (src[0] & mask) >> shift;
		return;
	}
	const size_t revShift = unitSize - shift;
	T prev = src[0];
	for (size_t i = 0; i < srcN - 2; i++) {
		T v = src[i + 1];
		dst[i] = (prev >> shift) | (v << revShift);
		prev = v;
	}
	// i = srcN - 1
	T v = src[srcN - 1] & mask;
	dst[srcN - 2] = (prev >> shift) | (v << revShift);
	if (srcN == dstN) {
		dst[srcN - 1] = v >> shift;
	}
}

} // cybozu::bitvector_local

template<class T>
class BitVectorT {
	static const size_t unitSize = sizeof(T) * 8;
	size_t bitLen_;
	std::vector<T> v_;
public:
	BitVectorT() : bitLen_(0) {}
	BitVectorT(const T *buf, size_t bitLen)
	{
		init(buf, bitLen);
	}
	void init(const T *buf, size_t bitLen)
	{
		resize(bitLen);
		std::copy(buf, buf + v_.size(), &v_[0]);
	}
	void resize(size_t bitLen)
	{
		bitLen_ = bitLen;
		const size_t n = RoundupBit<T>(bitLen);
		const size_t r = bitLen % unitSize;
		v_.resize(n);
		if (r) {
			v_[n - 1] &= GetMaskBit<T>(r);
		}
	}
	void reserve(size_t bitLen)
	{
		v_.reserve(RoundupBit<T>(bitLen));
	}
	bool get(size_t idx) const
	{
		if (idx >= bitLen_) throw cybozu::Exception("BitVectorT:get:bad idx") << idx;
		return GetBlockBit(v_.data(), idx);
	}
	void clear()
	{
		bitLen_ = 0;
		v_.clear();
	}
	void set(size_t idx, bool b)
	{
		if (b) {
			set(idx);
		} else {
			reset(idx);
		}
	}
	// set(idx, true);
	void set(size_t idx)
	{
		if (idx >= bitLen_) throw cybozu::Exception("BitVectorT:set:bad idx") << idx;
		SetBlockBit(v_.data(), idx);
	}
	// set(idx, false);
	void reset(size_t idx)
	{
		if (idx >= bitLen_) throw cybozu::Exception("BitVectorT:reset:bad idx") << idx;
		ResetBlockBit(v_.data(), idx);
	}
	size_t size() const { return bitLen_; }
	const T *getBlock() const { return &v_[0]; }
	T *getBlock() { return &v_[0]; }
	size_t getBlockSize() const { return v_.size(); }
	/*
		append src[0, bitLen)
	*/
	void append(const T* src, size_t bitLen)
	{
		if (bitLen == 0) return;
		const size_t q = bitLen_ / unitSize;
		const size_t r = bitLen_ % unitSize;
		resize(bitLen_ + bitLen);
		if (r == 0) {
			CopyBit<T>(&v_[q], src, bitLen);
			return;
		}
		bitvector_local::shiftLeftBit<T>(&v_[q], src, bitLen, r);
	}
	/*
		append src & mask(bitLen)
	*/
	void append(uint64_t src, size_t bitLen)
	{
		if (bitLen == 0) return;
		if (bitLen > unitSize) {
			throw cybozu::Exception("BitVectorT:append:bad bitLen") << bitLen;
		}
		if (bitLen < unitSize) {
			src &= GetMaskBit<T>(bitLen);
		}
		const size_t q = bitLen_ / unitSize;
		const size_t r = bitLen_ % unitSize;
		resize(bitLen_ + bitLen);
		if (r == 0) {
			v_[q] = T(src);
			return;
		}
		v_[q] |= T(src << r);
		if (r + bitLen > unitSize) {
			v_[q + 1] = T(src >> (unitSize - r));
		}
	}
	/*
		append bitVector
	*/
	void append(const BitVectorT<T>& v)
	{
		append(v.getBlock(), v.size());
	}
	/*
		dst[0, bitLen) = vec[pos, pos + bitLen)
	*/
	void extract(T* dst, size_t pos, size_t bitLen) const
	{
		if (bitLen == 0) return;
		if (pos + bitLen > bitLen_) {
			throw cybozu::Exception("BitVectorT:extract:bad range") << bitLen << pos << bitLen_;
		}
		const size_t q = pos / unitSize;
		const size_t r = pos % unitSize;
		if (r == 0) {
			CopyBit<T>(dst, &v_[q], bitLen);
			return;
		}
		bitvector_local::shiftRightBit<T>(dst, &v_[q], bitLen, r);
	}
	/*
		dst = vec[pos, pos + bitLen)
	*/
	void extract(BitVectorT<T>& dst, size_t pos, size_t bitLen) const
	{
		dst.resize(bitLen);
		extract(dst.getBlock(), pos, bitLen);
	}
	/*
		return vec[pos, pos + bitLen)
	*/
	T extract(size_t pos, size_t bitLen) const
	{
		if (bitLen == 0) return 0;
		if (bitLen > unitSize || pos + bitLen > bitLen_) {
			throw cybozu::Exception("BitVectorT:extract:bad range") << bitLen << pos << bitLen_;
		}
		const size_t q = pos / unitSize;
		const size_t r = pos % unitSize;
		T v;
		if (r == 0) {
			v = v_[q];
		} else if (q == v_.size() - 1) {
			v = v_[q] >> r;
		} else {
			v = (v_[q] >> r) | v_[q + 1] << (unitSize - r);
		}
		if (bitLen < unitSize) {
			v &= GetMaskBit<T>(bitLen);
		}
		return v;
	}
	bool operator==(const BitVectorT<T>& rhs) const { return v_ == rhs.v_; }
	bool operator!=(const BitVectorT<T>& rhs) const { return v_ != rhs.v_; }
};

typedef BitVectorT<size_t> BitVector;

} // cybozu
<commit_msg>rename unitSize to unitBitSize<commit_after>#pragma once
/**
	@file
	@brief bit vector
	@author MITSUNARI Shigeo(@herumi)
	@license modified new BSD license
	http://opensource.org/licenses/BSD-3-Clause
*/
#include <cybozu/exception.hpp>
#include <algorithm>
#include <vector>
#include <assert.h>

namespace cybozu {

template<class T>
size_t RoundupBit(size_t bitLen)
{
	const size_t unitBitSize = sizeof(T) * 8;
	return (bitLen + unitBitSize - 1) / unitBitSize;
}

template<class T>
T GetMaskBit(size_t bitLen)
{
	assert(bitLen < sizeof(T) * 8);
	return (T(1) << bitLen) - 1;
}

template<class T>
void SetBlockBit(T *buf, size_t bitLen)
{
	const size_t unitBitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitBitSize;
	const size_t r = bitLen % unitBitSize;
	buf[q] |= T(1) << r;
}
template<class T>
void ResetBlockBit(T *buf, size_t bitLen)
{
	const size_t unitBitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitBitSize;
	const size_t r = bitLen % unitBitSize;
	buf[q] &= ~(T(1) << r);
}
template<class T>
bool GetBlockBit(const T *buf, size_t bitLen)
{
	const size_t unitBitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitBitSize;
	const size_t r = bitLen % unitBitSize;
	return (buf[q] & (T(1) << r)) != 0;
}

template<class T>
void CopyBit(T* dst, const T* src, size_t bitLen)
{
	const size_t unitBitSize = sizeof(T) * 8;
	const size_t q = bitLen / unitBitSize;
	const size_t r = bitLen % unitBitSize;
	for (size_t i = 0; i < q; i++) dst[i] = src[i];
	if (r == 0) return;
	dst[q] = src[q] & GetMaskBit<T>(r);
}
/*
	dst[] = (src[] << shift) | ext
	@param dst [out] dst[0..bitLen)
	@param src [in] src[0..bitLen)
	@param bitLen [in] length of src, dst
	@param shift [in] 0 <= shift < unitBitSize
	@param ext [in] or bit
*/
template<class T>
T ShiftLeftBit(T* dst, const T* src, size_t bitLen, size_t shift, T ext = 0)
{
	if (bitLen == 0) return 0;
	const size_t unitBitSize = sizeof(T) * 8;
	if (shift >= unitBitSize) {
		throw cybozu::Exception("ShiftLeftBit:large shift") << shift;
	}
	const size_t n = RoundupBit<T>(bitLen); // n >= 1 because bitLen > 0
	const size_t r = bitLen % unitBitSize;
	const T mask = r > 0 ? GetMaskBit<T>(r) : T(-1);
	if (shift == 0) {
		if (n == 1) {
			dst[0] = (src[0] & mask) | ext;
		} else {
			dst[n - 1] = src[n - 1] & mask;
			for (size_t i = n - 2; i > 0; i--) {
				dst[i] = src[i];
			}
			dst[0] = src[0] | ext;
		}
		return 0;
	}
	const size_t revShift = unitBitSize - shift;
	T prev = src[n - 1] & mask;
	const T ret = prev >> revShift;
	for (size_t i = n - 1; i > 0; i--) {
		T v = src[i - 1];
		dst[i] = (prev << shift) | (v >> revShift);
		prev = v;
	}
	dst[0] = (prev << shift) | ext;
	return ret;
}

namespace bitvector_local {

/*
	dst[] = src[] << shift
	dst[0..shift) does not change

	@param dst [out] dst[shift..bitLen + shift)
	@param src [in] src[0..bitLen)
	@param bitLen [in] read bit size
	@param shift [in] 0 <= shift < unitBitSize
*/
template<class T>
void shiftLeftBit(T* dst, const T* src, size_t bitLen, size_t shift)
{
	const size_t unitBitSize = sizeof(T) * 8;

	assert(bitLen);
	assert(0 < shift && shift < unitBitSize);

	const size_t dstN = RoundupBit<T>(bitLen + shift);
	const size_t srcN = RoundupBit<T>(bitLen);
	const size_t r = bitLen % unitBitSize;
	const T mask = r ? GetMaskBit<T>(r) : T(-1);
	const size_t revShift = unitBitSize - shift;

	T prev = src[srcN - 1] & mask;
	if (dstN > srcN) {
		dst[dstN - 1] = prev >> revShift;
	}
	for (size_t i = srcN - 1; i > 0; i--) {
		T v = src[i - 1];
		dst[i] = (prev << shift) | (v >> revShift);
		prev = v;
	}
	T ext = dst[0] & GetMaskBit<T>(shift);
	dst[0] = (prev << shift) | ext;
}

/*
	dst[] = src[] >> shift

	@param dst [out] dst[0..bitLen)
	@param src [in] src[shift..bitLen + shift)
	@param bitLen [in] write bit size
	@param shift [in] 0 <= shift < unitBitSize
	@note src[bitLen + shift - 1] is accessable
*/
template<class T>
void shiftRightBit(T* dst, const T* src, size_t bitLen, size_t shift)
{
	const size_t unitBitSize = sizeof(T) * 8;

	assert(bitLen);
	assert(0 < shift && shift < unitBitSize);

	const size_t dstN = RoundupBit<T>(bitLen);
	const size_t srcN = RoundupBit<T>(bitLen + shift);// srcN = dstN, dstN + 1
	const size_t r = (bitLen + shift) % unitBitSize;
	const T mask = r ? GetMaskBit<T>(r) : T(-1);
	if (srcN == 1) {
		dst[0] = (src[0] & mask) >> shift;
		return;
	}
	const size_t revShift = unitBitSize - shift;
	T prev = src[0];
	for (size_t i = 0; i < srcN - 2; i++) {
		T v = src[i + 1];
		dst[i] = (prev >> shift) | (v << revShift);
		prev = v;
	}
	// i = srcN - 1
	T v = src[srcN - 1] & mask;
	dst[srcN - 2] = (prev >> shift) | (v << revShift);
	if (srcN == dstN) {
		dst[srcN - 1] = v >> shift;
	}
}

} // cybozu::bitvector_local

template<class T>
class BitVectorT {
	static const size_t unitBitSize = sizeof(T) * 8;
	size_t bitLen_;
	std::vector<T> v_;
public:
	typedef T value_type;
	BitVectorT() : bitLen_(0) {}
	BitVectorT(const T *buf, size_t bitLen)
	{
		init(buf, bitLen);
	}
	void init(const T *buf, size_t bitLen)
	{
		resize(bitLen);
		std::copy(buf, buf + v_.size(), &v_[0]);
	}
	void resize(size_t bitLen)
	{
		bitLen_ = bitLen;
		const size_t n = RoundupBit<T>(bitLen);
		const size_t r = bitLen % unitBitSize;
		v_.resize(n);
		if (r) {
			v_[n - 1] &= GetMaskBit<T>(r);
		}
	}
	void reserve(size_t bitLen)
	{
		v_.reserve(RoundupBit<T>(bitLen));
	}
	bool get(size_t idx) const
	{
		if (idx >= bitLen_) throw cybozu::Exception("BitVectorT:get:bad idx") << idx;
		return GetBlockBit(v_.data(), idx);
	}
	void clear()
	{
		bitLen_ = 0;
		v_.clear();
	}
	void set(size_t idx, bool b)
	{
		if (b) {
			set(idx);
		} else {
			reset(idx);
		}
	}
	// set(idx, true);
	void set(size_t idx)
	{
		if (idx >= bitLen_) throw cybozu::Exception("BitVectorT:set:bad idx") << idx;
		SetBlockBit(v_.data(), idx);
	}
	// set(idx, false);
	void reset(size_t idx)
	{
		if (idx >= bitLen_) throw cybozu::Exception("BitVectorT:reset:bad idx") << idx;
		ResetBlockBit(v_.data(), idx);
	}
	size_t size() const { return bitLen_; }
	const T *getBlock() const { return &v_[0]; }
	T *getBlock() { return &v_[0]; }
	size_t getBlockSize() const { return v_.size(); }
	/*
		append src[0, bitLen)
	*/
	void append(const T* src, size_t bitLen)
	{
		if (bitLen == 0) return;
		const size_t q = bitLen_ / unitBitSize;
		const size_t r = bitLen_ % unitBitSize;
		resize(bitLen_ + bitLen);
		if (r == 0) {
			CopyBit<T>(&v_[q], src, bitLen);
			return;
		}
		bitvector_local::shiftLeftBit<T>(&v_[q], src, bitLen, r);
	}
	/*
		append src & mask(bitLen)
	*/
	void append(uint64_t src, size_t bitLen)
	{
		if (bitLen == 0) return;
		if (bitLen > unitBitSize) {
			throw cybozu::Exception("BitVectorT:append:bad bitLen") << bitLen;
		}
		if (bitLen < unitBitSize) {
			src &= GetMaskBit<T>(bitLen);
		}
		const size_t q = bitLen_ / unitBitSize;
		const size_t r = bitLen_ % unitBitSize;
		resize(bitLen_ + bitLen);
		if (r == 0) {
			v_[q] = T(src);
			return;
		}
		v_[q] |= T(src << r);
		if (r + bitLen > unitBitSize) {
			v_[q + 1] = T(src >> (unitBitSize - r));
		}
	}
	/*
		append bitVector
	*/
	void append(const BitVectorT<T>& v)
	{
		append(v.getBlock(), v.size());
	}
	/*
		dst[0, bitLen) = vec[pos, pos + bitLen)
	*/
	void extract(T* dst, size_t pos, size_t bitLen) const
	{
		if (bitLen == 0) return;
		if (pos + bitLen > bitLen_) {
			throw cybozu::Exception("BitVectorT:extract:bad range") << bitLen << pos << bitLen_;
		}
		const size_t q = pos / unitBitSize;
		const size_t r = pos % unitBitSize;
		if (r == 0) {
			CopyBit<T>(dst, &v_[q], bitLen);
			return;
		}
		bitvector_local::shiftRightBit<T>(dst, &v_[q], bitLen, r);
	}
	/*
		dst = vec[pos, pos + bitLen)
	*/
	void extract(BitVectorT<T>& dst, size_t pos, size_t bitLen) const
	{
		dst.resize(bitLen);
		extract(dst.getBlock(), pos, bitLen);
	}
	/*
		return vec[pos, pos + bitLen)
	*/
	T extract(size_t pos, size_t bitLen) const
	{
		if (bitLen == 0) return 0;
		if (bitLen > unitBitSize || pos + bitLen > bitLen_) {
			throw cybozu::Exception("BitVectorT:extract:bad range") << bitLen << pos << bitLen_;
		}
		const size_t q = pos / unitBitSize;
		const size_t r = pos % unitBitSize;
		T v;
		if (r == 0) {
			v = v_[q];
		} else if (q == v_.size() - 1) {
			v = v_[q] >> r;
		} else {
			v = (v_[q] >> r) | v_[q + 1] << (unitBitSize - r);
		}
		if (bitLen < unitBitSize) {
			v &= GetMaskBit<T>(bitLen);
		}
		return v;
	}
	bool operator==(const BitVectorT<T>& rhs) const { return v_ == rhs.v_; }
	bool operator!=(const BitVectorT<T>& rhs) const { return v_ != rhs.v_; }
};

typedef BitVectorT<size_t> BitVector;

} // cybozu
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Marcin Kościelnicki <koriakin@0x04.net>
 * All Rights Reserved.
 *
 * 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 (including the next
 * paragraph) 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.
 */

#include "pgraph.h"
#include "pgraph_mthd.h"
#include "pgraph_class.h"
#include "nva.h"

namespace hwtest {
namespace pgraph {

std::vector<SingleMthdTest *> EmuCelsius::mthds() {
	std::vector<SingleMthdTest *> res = {
		new MthdNop(opt, rnd(), "nop", -1, cls, 0x100),
		new MthdNotify(opt, rnd(), "notify", -1, cls, 0x104),
		new MthdWarning(opt, rnd(), "warning", -1, cls, 0x108),
		new MthdState(opt, rnd(), "state", -1, cls, 0x10c),
		new MthdSync(opt, rnd(), "sync", -1, cls, 0x110),
		new MthdPmTrigger(opt, rnd(), "pm_trigger", -1, cls, 0x140),
		new MthdDmaNotify(opt, rnd(), "dma_notify", -1, cls, 0x180),
		new UntestedMthd(opt, rnd(), "dma_tex_a", -1, cls, 0x184), // XXX
		new UntestedMthd(opt, rnd(), "dma_tex_b", -1, cls, 0x188), // XXX
		new UntestedMthd(opt, rnd(), "dma_vtx", -1, cls, 0x18c), // XXX
		new UntestedMthd(opt, rnd(), "dma_state", -1, cls, 0x190), // XXX
		new MthdDmaSurf(opt, rnd(), "dma_surf_color", -1, cls, 0x194, 2, SURF_NV10),
		new MthdDmaSurf(opt, rnd(), "dma_surf_zeta", -1, cls, 0x198, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "clip_h", -1, cls, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "clip_v", -1, cls, 0x204), // XXX
		new MthdSurf3DFormat(opt, rnd(), "surf_format", -1, cls, 0x208, true),
		new MthdSurfPitch2(opt, rnd(), "surf_pitch_2", -1, cls, 0x20c, 2, 3, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "color_offset", -1, cls, 0x210, 2, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "zeta_offset", -1, cls, 0x214, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x218, 2), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x220, 8), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x240, 0x10), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x280, 0x20), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x300, 0x40), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x400, 0x100), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x800, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x1000, 0x400), // XXX
	};
	if (cls == 0x56) {
	} else {
		res.insert(res.end(), {
			new UntestedMthd(opt, rnd(), "unk114", -1, cls, 0x114), // XXX
			new MthdFlipSet(opt, rnd(), "flip_write", -1, cls, 0x120, 1, 1),
			new MthdFlipSet(opt, rnd(), "flip_read", -1, cls, 0x124, 1, 0),
			new MthdFlipSet(opt, rnd(), "flip_modulo", -1, cls, 0x128, 1, 2),
			new MthdFlipBumpWrite(opt, rnd(), "flip_bump_write", -1, cls, 0x12c, 1),
			new UntestedMthd(opt, rnd(), "flip_unk130", -1, cls, 0x130),
		});
	}
	return res;
}

std::vector<SingleMthdTest *> Kelvin::mthds() {
	std::vector<SingleMthdTest *> res = {
		new MthdNop(opt, rnd(), "nop", -1, cls, 0x100),
		new MthdNotify(opt, rnd(), "notify", -1, cls, 0x104),
		new MthdWarning(opt, rnd(), "warning", -1, cls, 0x108),
		new MthdState(opt, rnd(), "state", -1, cls, 0x10c),
		new MthdSync(opt, rnd(), "sync", -1, cls, 0x110),
		new MthdFlipSet(opt, rnd(), "flip_write", -1, cls, 0x120, 1, 1),
		new MthdFlipSet(opt, rnd(), "flip_read", -1, cls, 0x124, 1, 0),
		new MthdFlipSet(opt, rnd(), "flip_modulo", -1, cls, 0x128, 1, 2),
		new MthdFlipBumpWrite(opt, rnd(), "flip_bump_write", -1, cls, 0x12c, 1),
		new UntestedMthd(opt, rnd(), "flip_unk130", -1, cls, 0x130),
		new MthdPmTrigger(opt, rnd(), "pm_trigger", -1, cls, 0x140),
		new MthdDmaNotify(opt, rnd(), "dma_notify", -1, cls, 0x180),
		new UntestedMthd(opt, rnd(), "dma_tex_a", -1, cls, 0x184), // XXX
		new UntestedMthd(opt, rnd(), "dma_tex_b", -1, cls, 0x188), // XXX
		new UntestedMthd(opt, rnd(), "dma_state", -1, cls, 0x190), // XXX
		new MthdDmaSurf(opt, rnd(), "dma_surf_color", -1, cls, 0x194, 2, SURF_NV10),
		new MthdDmaSurf(opt, rnd(), "dma_surf_zeta", -1, cls, 0x198, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "dma_vtx_a", -1, cls, 0x19c), // XXX
		new UntestedMthd(opt, rnd(), "dma_vtx_b", -1, cls, 0x1a0), // XXX
		new UntestedMthd(opt, rnd(), "dma_fence", -1, cls, 0x1a4), // XXX
		new UntestedMthd(opt, rnd(), "dma_query", -1, cls, 0x1a8), // XXX
		new UntestedMthd(opt, rnd(), "clip_h", -1, cls, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "clip_v", -1, cls, 0x204), // XXX
		new MthdSurf3DFormat(opt, rnd(), "surf_format", -1, cls, 0x208, true),
		new MthdSurfPitch2(opt, rnd(), "surf_pitch_2", -1, cls, 0x20c, 2, 3, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "color_offset", -1, cls, 0x210, 2, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "zeta_offset", -1, cls, 0x214, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x218, 2), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x220, 8), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x240, 0x10), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x280, 0x20), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x300, 0x40), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x400, 0x100), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x800, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x1000, 0x400), // XXX
	};
	if (cls == 0x597) {
		res.insert(res.end(), {
			new UntestedMthd(opt, rnd(), "dma_clipid", -1, cls, 0x1ac),
			new UntestedMthd(opt, rnd(), "dma_zcull", -1, cls, 0x1b0),
		});
	}
	return res;
}

}
}
<commit_msg>hwtest/pgraph: Bring back trapbits to EmuCelsius.<commit_after>/*
 * Copyright (C) 2016 Marcin Kościelnicki <koriakin@0x04.net>
 * All Rights Reserved.
 *
 * 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 (including the next
 * paragraph) 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.
 */

#include "pgraph.h"
#include "pgraph_mthd.h"
#include "pgraph_class.h"
#include "nva.h"

namespace hwtest {
namespace pgraph {

std::vector<SingleMthdTest *> EmuCelsius::mthds() {
	std::vector<SingleMthdTest *> res = {
		new MthdNop(opt, rnd(), "nop", -1, cls, 0x100),
		new MthdNotify(opt, rnd(), "notify", 0, cls, 0x104),
		new MthdWarning(opt, rnd(), "warning", 2, cls, 0x108),
		new MthdState(opt, rnd(), "state", -1, cls, 0x10c),
		new MthdSync(opt, rnd(), "sync", 1, cls, 0x110),
		new MthdPmTrigger(opt, rnd(), "pm_trigger", -1, cls, 0x140),
		new MthdDmaNotify(opt, rnd(), "dma_notify", 3, cls, 0x180),
		new UntestedMthd(opt, rnd(), "dma_tex_a", 4, cls, 0x184), // XXX
		new UntestedMthd(opt, rnd(), "dma_tex_b", 5, cls, 0x188), // XXX
		new UntestedMthd(opt, rnd(), "dma_vtx", 6, cls, 0x18c), // XXX
		new UntestedMthd(opt, rnd(), "dma_state", 7, cls, 0x190), // XXX
		new MthdDmaSurf(opt, rnd(), "dma_surf_color", 8, cls, 0x194, 2, SURF_NV10),
		new MthdDmaSurf(opt, rnd(), "dma_surf_zeta", 9, cls, 0x198, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "clip_h", 10, cls, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "clip_v", 10, cls, 0x204), // XXX
		new MthdSurf3DFormat(opt, rnd(), "surf_format", 11, cls, 0x208, true),
		new MthdSurfPitch2(opt, rnd(), "surf_pitch_2", 12, cls, 0x20c, 2, 3, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "color_offset", 13, cls, 0x210, 2, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "zeta_offset", 14, cls, 0x214, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x218, 2), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x220, 8), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x240, 0x10), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x280, 0x20), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x300, 0x40), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x400, 0x100), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x800, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x1000, 0x400), // XXX
	};
	if (cls == 0x56) {
	} else {
		res.insert(res.end(), {
			new UntestedMthd(opt, rnd(), "unk114", -1, cls, 0x114), // XXX
			new MthdFlipSet(opt, rnd(), "flip_write", -1, cls, 0x120, 1, 1),
			new MthdFlipSet(opt, rnd(), "flip_read", -1, cls, 0x124, 1, 0),
			new MthdFlipSet(opt, rnd(), "flip_modulo", -1, cls, 0x128, 1, 2),
			new MthdFlipBumpWrite(opt, rnd(), "flip_bump_write", -1, cls, 0x12c, 1),
			new UntestedMthd(opt, rnd(), "flip_unk130", -1, cls, 0x130),
		});
	}
	return res;
}

std::vector<SingleMthdTest *> Kelvin::mthds() {
	std::vector<SingleMthdTest *> res = {
		new MthdNop(opt, rnd(), "nop", -1, cls, 0x100),
		new MthdNotify(opt, rnd(), "notify", -1, cls, 0x104),
		new MthdWarning(opt, rnd(), "warning", -1, cls, 0x108),
		new MthdState(opt, rnd(), "state", -1, cls, 0x10c),
		new MthdSync(opt, rnd(), "sync", -1, cls, 0x110),
		new MthdFlipSet(opt, rnd(), "flip_write", -1, cls, 0x120, 1, 1),
		new MthdFlipSet(opt, rnd(), "flip_read", -1, cls, 0x124, 1, 0),
		new MthdFlipSet(opt, rnd(), "flip_modulo", -1, cls, 0x128, 1, 2),
		new MthdFlipBumpWrite(opt, rnd(), "flip_bump_write", -1, cls, 0x12c, 1),
		new UntestedMthd(opt, rnd(), "flip_unk130", -1, cls, 0x130),
		new MthdPmTrigger(opt, rnd(), "pm_trigger", -1, cls, 0x140),
		new MthdDmaNotify(opt, rnd(), "dma_notify", -1, cls, 0x180),
		new UntestedMthd(opt, rnd(), "dma_tex_a", -1, cls, 0x184), // XXX
		new UntestedMthd(opt, rnd(), "dma_tex_b", -1, cls, 0x188), // XXX
		new UntestedMthd(opt, rnd(), "dma_state", -1, cls, 0x190), // XXX
		new MthdDmaSurf(opt, rnd(), "dma_surf_color", -1, cls, 0x194, 2, SURF_NV10),
		new MthdDmaSurf(opt, rnd(), "dma_surf_zeta", -1, cls, 0x198, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "dma_vtx_a", -1, cls, 0x19c), // XXX
		new UntestedMthd(opt, rnd(), "dma_vtx_b", -1, cls, 0x1a0), // XXX
		new UntestedMthd(opt, rnd(), "dma_fence", -1, cls, 0x1a4), // XXX
		new UntestedMthd(opt, rnd(), "dma_query", -1, cls, 0x1a8), // XXX
		new UntestedMthd(opt, rnd(), "clip_h", -1, cls, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "clip_v", -1, cls, 0x204), // XXX
		new MthdSurf3DFormat(opt, rnd(), "surf_format", -1, cls, 0x208, true),
		new MthdSurfPitch2(opt, rnd(), "surf_pitch_2", -1, cls, 0x20c, 2, 3, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "color_offset", -1, cls, 0x210, 2, SURF_NV10),
		new MthdSurfOffset(opt, rnd(), "zeta_offset", -1, cls, 0x214, 3, SURF_NV10),
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x218, 2), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x220, 8), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x240, 0x10), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x280, 0x20), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x300, 0x40), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x400, 0x100), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x800, 0x200), // XXX
		new UntestedMthd(opt, rnd(), "meh", -1, cls, 0x1000, 0x400), // XXX
	};
	if (cls == 0x597) {
		res.insert(res.end(), {
			new UntestedMthd(opt, rnd(), "dma_clipid", -1, cls, 0x1ac),
			new UntestedMthd(opt, rnd(), "dma_zcull", -1, cls, 0x1b0),
		});
	}
	return res;
}

}
}
<|endoftext|>


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

#include "boost/filesystem.hpp"
#include "OdPlatformSettings.h"

#include "vectorise_device_rvt.h"
#include "vectorise_view_rvt.h"
#include "helper_functions.h"

using namespace repo::manipulator::modelconvertor::odaHelper;

const char* RVT_TEXTURES_ENV_VARIABLE = "RVT_TEXTURES";

std::string getElementName(OdBmElementPtr element, uint64_t id)
{
	std::string elName(convertToStdString(element->getElementName()));
	if (!elName.empty())
		elName.append("_");

	elName.append(std::to_string(id));

	return elName;
}

bool isFileExist(const std::string& inputPath)
{
	if (boost::filesystem::exists(inputPath))
		if (boost::filesystem::is_regular_file(inputPath))
			return true;

	return false;
}

std::string extractValidTexturePath(const std::string& inputPath)
{
	std::string outputFilePath = inputPath;

	//..try to extract one valid paths if multiple paths are provided
	outputFilePath = outputFilePath.substr(0, outputFilePath.find("|", 0));

	if (isFileExist(outputFilePath))
		return outputFilePath;

	//..try to apply absolute path
	char* env = std::getenv(RVT_TEXTURES_ENV_VARIABLE);
	if (env == nullptr)
		return std::string();

	auto absolutePath = boost::filesystem::absolute(outputFilePath, env);
	outputFilePath = absolutePath.generic_string();

	if (isFileExist(outputFilePath))
		return outputFilePath;

	return std::string();
}

std::string variantToString(const OdTfVariant& val, OdBmLabelUtilsPEPtr labelUtils, OdBmParamDefPtr paramDef, OdBmDatabase* database, OdBm::BuiltInParameterDefinition::Enum param)
{
	std::string strOut;
	switch (val.type()) {
	case OdTfVariant::kString:
		strOut = convertToStdString(val.getString());
		break;
	case OdTfVariant::kBool:
		strOut = std::to_string(val.getBool());
		break;
	case OdTfVariant::kInt8:
		strOut = std::to_string(val.getInt8());
		break;
	case OdTfVariant::kInt16:
		strOut = std::to_string(val.getInt16());
		break;
	case OdTfVariant::kInt32:
		if (paramDef->getParameterType() == OdBm::ParameterType::YesNo)
			(val.getInt32()) ? strOut = "Yes" : strOut = "No";
		else
			strOut = std::to_string(val.getInt32());
		break;
	case OdTfVariant::kInt64:
		strOut = std::to_string(val.getInt64());
		break;
	case OdTfVariant::kDouble:
		strOut = convertToStdString(labelUtils->format(*database->getUnits(), paramDef->getUnitType(), val.getDouble(), false));
		break;
	case OdTfVariant::kDbStubPtr:
			OdDbStub* stub = val.getDbStubPtr();
			if (stub)
			{
				OdBmObjectId rawValue = OdBmObjectId(stub);
				if (param == OdBm::BuiltInParameter::ELEM_CATEGORY_PARAM || param == OdBm::BuiltInParameter::ELEM_CATEGORY_PARAM_MT)
				{
					OdDbHandle hdl = rawValue.getHandle();
					if (OdBmObjectId::isRegularHandle(hdl))
					{
						strOut = std::to_string((OdUInt64)hdl);
					}
					else
					{
						OdBm::BuiltInCategory::Enum builtInValue = static_cast<OdBm::BuiltInCategory::Enum>((OdUInt64)rawValue.getHandle());
						strOut = convertToStdString(OdBm::BuiltInCategory(builtInValue).toString());
					}
				}
				else
				{
					OdBmElementPtr elem = database->getObjectId(rawValue.getHandle()).safeOpenObject();
					strOut = (elem->getElementName() == OdString::kEmpty) ? std::to_string((OdUInt64)rawValue.getHandle()) : convertToStdString(elem->getElementName());
				}
			}
	}

	return strOut;
}

OdGsViewPtr VectorizeView::createObject(GeometryCollector* geoColl)
{
	auto ptr = OdRxObjectImpl<VectorizeView, OdGsView>::createObject();
	static_cast<VectorizeView*>(ptr.get())->collector = geoColl;
	return ptr;
}

VectorizeView::VectorizeView()
{
	meshesCount = 0;
}

void VectorizeView::draw(const OdGiDrawable* pDrawable)
{
	fillMeshData(pDrawable);
	OdGsBaseMaterialView::draw(pDrawable);
}

VectoriseDeviceRvt* VectorizeView::device()
{
	return (VectoriseDeviceRvt*)OdGsBaseVectorizeView::device();
}

void VectorizeView::OnFillMaterialCache(
	OdGiMaterialItemPtr prevCache,
	OdDbStub* materialId,
	const OdGiMaterialTraitsData & materialData,
	const MaterialColors& matColors,
	repo_material_t& material)
{
	bool missingTexture = false;
	fillMaterial(matColors, material);
	fillTexture(materialId, material, missingTexture);

	collector->setCurrentMaterial(material, missingTexture);
	collector->stopMeshEntry();
	collector->startMeshEntry();
}

void VectorizeView::OnTriangleOut(const std::vector<repo::lib::RepoVector3D64>& vertices)
{
	const int numVertices = 3;
	if (vertices.size() != numVertices)
		return;

	OdGiMapperItemEntry::MapInputTriangle trg;

	for (int i = 0; i < vertices.size(); ++i)
	{
		trg.inPt[i].x = vertices[i].x;
		trg.inPt[i].y = vertices[i].y;
		trg.inPt[i].z = vertices[i].z;
	}

	OdGiMapperItemEntry::MapOutputCoords outTex;

	auto currentMap = currentMapper();
	if (!currentMap.isNull())
	{
		auto diffuseMap = currentMap->diffuseMapper();
		if (!diffuseMap.isNull())
			diffuseMap->mapCoords(trg, outTex);
	}

	std::vector<repo::lib::RepoVector2D> uvc;
	for (int i = 0; i < numVertices; ++i)
		uvc.push_back({ (float)outTex.outCoord[i].x, (float)outTex.outCoord[i].y });

	collector->addFace(vertices, uvc);
}

std::string VectorizeView::getLevel(OdBmElementPtr element, const std::string& name)
{
	auto levelId = element->getAssocLevelId();
	if (levelId.isValid())
	{
		auto levelObject = levelId.safeOpenObject();
		if (!levelObject.isNull())
		{
			OdBmLevelPtr lptr = OdBmLevel::cast(levelObject);
			if (!lptr.isNull())
				return std::string(convertToStdString(lptr->getElementName()));
		}
	}

	auto owner = element->getOwningElementId();
	if (owner.isValid())
	{
		auto object = owner.openObject();
		if (!object.isNull())
		{
			auto parentElement = OdBmElement::cast(object);
			if (!parentElement.isNull())
				return getLevel(parentElement, name);
		}
	}

	return name;
}

void VectorizeView::fillMeshData(const OdGiDrawable* pDrawable)
{
	OdBmElementPtr element = OdBmElement::cast(pDrawable);
	if (element.isNull())
		return;

	if (!element->isDBRO())
		return;

	std::string elementName = getElementName(element, meshesCount);

	collector->setNextMeshName(elementName);
	collector->setMeshGroup(elementName);

	try
	{
		collector->setCurrentMeta(fillMetadata(element));
	}
	catch(OdError& er)
	{
		//..Hotfix: handle nullPtr exception (need to check updated library)
	}

	meshesCount++;

	std::string layerName = getLevel(element, "Layer Default");
	collector->setLayer(layerName);
}

std::pair<std::vector<std::string>, std::vector<std::string>> VectorizeView::fillMetadata(OdBmElementPtr element)
{
	std::pair<std::vector<std::string>, std::vector<std::string>> metadata;

	OdBuiltInParamArray aParams;
	element->getListParams(aParams);

	OdBmLabelUtilsPEPtr labelUtils = OdBmObject::desc()->getX(OdBmLabelUtilsPE::desc());
	if (labelUtils.isNull())
		return metadata;

	for (OdBuiltInParamArray::iterator it = aParams.begin(); it != aParams.end(); it++)
	{
		std::string builtInName = convertToStdString(OdBm::BuiltInParameter(*it).toString());

		//..Hotfix: handle access violation exception (need to check updated library)
		if (builtInName == std::string("ROOF_SLOPE"))
			continue;

		std::string paramName;
		if (!labelUtils->getLabelFor(*it).isEmpty())
			paramName = convertToStdString(labelUtils->getLabelFor(*it));
		else
			paramName = builtInName;

		OdTfVariant value;
		OdResult res = element->getParam(*it, value);
		if (res == eOk)
		{
			OdBmParamElemPtr pParamElem = element->database()->getObjectId(*it).safeOpenObject();
			OdBmParamDefPtr pDescParam = pParamElem->getParamDef();

			std::string variantValue = variantToString(value, labelUtils, pDescParam, element->getDatabase(), *it);
			if (!variantValue.empty())
			{
				metadata.first.push_back(convertToStdString(pDescParam->getCaption()));
				metadata.second.push_back(variantValue);
			}
		}
	}

	return metadata;
}

void VectorizeView::fillMaterial(const MaterialColors& matColors, repo_material_t& material)
{
	const float norm = 255.f;

	material.diffuse = { ODGETRED(matColors.colorDiffuse) / norm, ODGETGREEN(matColors.colorDiffuse) / norm, ODGETBLUE(matColors.colorDiffuse) / norm, 1.0f };
	material.specular = { ODGETRED(matColors.colorSpecular) / norm, ODGETGREEN(matColors.colorSpecular) / norm, ODGETBLUE(matColors.colorSpecular) / norm, 1.0f };
	material.ambient = { ODGETRED(matColors.colorAmbient) / norm, ODGETGREEN(matColors.colorAmbient) / norm, ODGETBLUE(matColors.colorAmbient) / norm, 1.0f };
	material.emissive = { ODGETRED(matColors.colorEmissive) / norm, ODGETGREEN(matColors.colorEmissive) / norm, ODGETBLUE(matColors.colorEmissive) / norm, 1.0f };
}

void VectorizeView::fillTexture(OdDbStub* materialId, repo_material_t& material, bool& missingTexture)
{
	missingTexture = false;

	OdBmObjectId matId(materialId);
	if (!matId.isValid())
		return;

	OdBmObjectPtr materialPtr = matId.safeOpenObject(OdBm::kForRead);
	OdBmMaterialElemPtr materialElem = (OdBmMaterialElem*)(materialPtr.get());
	OdBmMaterialPtr matPtr = materialElem->getMaterial();
	OdBmAssetPtr textureAsset = matPtr->getAsset();

	if (textureAsset.isNull())
		return;

	OdBmAssetPtr bitmapAsset;
	OdString textureFileName;
	OdResult es = OdBmAppearanceAssetHelper::getTextureAsset(textureAsset, bitmapAsset);

	if ((es != OdResult::eOk) || (bitmapAsset.isNull()))
		return;

	OdBmUnifiedBitmapSchemaHelper textureHelper(bitmapAsset);
	es = textureHelper.getTextureFileName(textureFileName);

	if (es != OdResult::eOk)
		return;

	std::string textureName(convertToStdString(textureFileName));
	std::string validTextureName = extractValidTexturePath(textureName);

	if (validTextureName.empty() && !textureName.empty())
		missingTexture = true;

	material.texturePath = validTextureName;
}<commit_msg>ISSUE #291 - disable shininess and shininessStrength<commit_after>/**
*  Copyright (C) 2018 3D Repo Ltd
*
*  This program is free software: you can redistribute it and/or modify
*  it under the terms of the GNU Affero General Public License as
*  published by the Free Software Foundation, either version 3 of the
*  License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Affero General Public License for more details.
*
*  You should have received a copy of the GNU Affero General Public License
*  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "boost/filesystem.hpp"
#include "OdPlatformSettings.h"

#include "vectorise_device_rvt.h"
#include "vectorise_view_rvt.h"
#include "helper_functions.h"

using namespace repo::manipulator::modelconvertor::odaHelper;

const char* RVT_TEXTURES_ENV_VARIABLE = "RVT_TEXTURES";

std::string getElementName(OdBmElementPtr element, uint64_t id)
{
	std::string elName(convertToStdString(element->getElementName()));
	if (!elName.empty())
		elName.append("_");

	elName.append(std::to_string(id));

	return elName;
}

bool isFileExist(const std::string& inputPath)
{
	if (boost::filesystem::exists(inputPath))
		if (boost::filesystem::is_regular_file(inputPath))
			return true;

	return false;
}

std::string extractValidTexturePath(const std::string& inputPath)
{
	std::string outputFilePath = inputPath;

	//..try to extract one valid paths if multiple paths are provided
	outputFilePath = outputFilePath.substr(0, outputFilePath.find("|", 0));

	if (isFileExist(outputFilePath))
		return outputFilePath;

	//..try to apply absolute path
	char* env = std::getenv(RVT_TEXTURES_ENV_VARIABLE);
	if (env == nullptr)
		return std::string();

	auto absolutePath = boost::filesystem::absolute(outputFilePath, env);
	outputFilePath = absolutePath.generic_string();

	if (isFileExist(outputFilePath))
		return outputFilePath;

	return std::string();
}

std::string variantToString(const OdTfVariant& val, OdBmLabelUtilsPEPtr labelUtils, OdBmParamDefPtr paramDef, OdBmDatabase* database, OdBm::BuiltInParameterDefinition::Enum param)
{
	std::string strOut;
	switch (val.type()) {
	case OdTfVariant::kString:
		strOut = convertToStdString(val.getString());
		break;
	case OdTfVariant::kBool:
		strOut = std::to_string(val.getBool());
		break;
	case OdTfVariant::kInt8:
		strOut = std::to_string(val.getInt8());
		break;
	case OdTfVariant::kInt16:
		strOut = std::to_string(val.getInt16());
		break;
	case OdTfVariant::kInt32:
		if (paramDef->getParameterType() == OdBm::ParameterType::YesNo)
			(val.getInt32()) ? strOut = "Yes" : strOut = "No";
		else
			strOut = std::to_string(val.getInt32());
		break;
	case OdTfVariant::kInt64:
		strOut = std::to_string(val.getInt64());
		break;
	case OdTfVariant::kDouble:
		strOut = convertToStdString(labelUtils->format(*database->getUnits(), paramDef->getUnitType(), val.getDouble(), false));
		break;
	case OdTfVariant::kDbStubPtr:
			OdDbStub* stub = val.getDbStubPtr();
			if (stub)
			{
				OdBmObjectId rawValue = OdBmObjectId(stub);
				if (param == OdBm::BuiltInParameter::ELEM_CATEGORY_PARAM || param == OdBm::BuiltInParameter::ELEM_CATEGORY_PARAM_MT)
				{
					OdDbHandle hdl = rawValue.getHandle();
					if (OdBmObjectId::isRegularHandle(hdl))
					{
						strOut = std::to_string((OdUInt64)hdl);
					}
					else
					{
						OdBm::BuiltInCategory::Enum builtInValue = static_cast<OdBm::BuiltInCategory::Enum>((OdUInt64)rawValue.getHandle());
						strOut = convertToStdString(OdBm::BuiltInCategory(builtInValue).toString());
					}
				}
				else
				{
					OdBmElementPtr elem = database->getObjectId(rawValue.getHandle()).safeOpenObject();
					strOut = (elem->getElementName() == OdString::kEmpty) ? std::to_string((OdUInt64)rawValue.getHandle()) : convertToStdString(elem->getElementName());
				}
			}
	}

	return strOut;
}

OdGsViewPtr VectorizeView::createObject(GeometryCollector* geoColl)
{
	auto ptr = OdRxObjectImpl<VectorizeView, OdGsView>::createObject();
	static_cast<VectorizeView*>(ptr.get())->collector = geoColl;
	return ptr;
}

VectorizeView::VectorizeView()
{
	meshesCount = 0;
}

void VectorizeView::draw(const OdGiDrawable* pDrawable)
{
	fillMeshData(pDrawable);
	OdGsBaseMaterialView::draw(pDrawable);
}

VectoriseDeviceRvt* VectorizeView::device()
{
	return (VectoriseDeviceRvt*)OdGsBaseVectorizeView::device();
}

void VectorizeView::OnFillMaterialCache(
	OdGiMaterialItemPtr prevCache,
	OdDbStub* materialId,
	const OdGiMaterialTraitsData & materialData,
	const MaterialColors& matColors,
	repo_material_t& material)
{
	bool missingTexture = false;
	fillMaterial(matColors, material);
	fillTexture(materialId, material, missingTexture);

	collector->setCurrentMaterial(material, missingTexture);
	collector->stopMeshEntry();
	collector->startMeshEntry();
}

void VectorizeView::OnTriangleOut(const std::vector<repo::lib::RepoVector3D64>& vertices)
{
	const int numVertices = 3;
	if (vertices.size() != numVertices)
		return;

	OdGiMapperItemEntry::MapInputTriangle trg;

	for (int i = 0; i < vertices.size(); ++i)
	{
		trg.inPt[i].x = vertices[i].x;
		trg.inPt[i].y = vertices[i].y;
		trg.inPt[i].z = vertices[i].z;
	}

	OdGiMapperItemEntry::MapOutputCoords outTex;

	auto currentMap = currentMapper();
	if (!currentMap.isNull())
	{
		auto diffuseMap = currentMap->diffuseMapper();
		if (!diffuseMap.isNull())
			diffuseMap->mapCoords(trg, outTex);
	}

	std::vector<repo::lib::RepoVector2D> uvc;
	for (int i = 0; i < numVertices; ++i)
		uvc.push_back({ (float)outTex.outCoord[i].x, (float)outTex.outCoord[i].y });

	collector->addFace(vertices, uvc);
}

std::string VectorizeView::getLevel(OdBmElementPtr element, const std::string& name)
{
	auto levelId = element->getAssocLevelId();
	if (levelId.isValid())
	{
		auto levelObject = levelId.safeOpenObject();
		if (!levelObject.isNull())
		{
			OdBmLevelPtr lptr = OdBmLevel::cast(levelObject);
			if (!lptr.isNull())
				return std::string(convertToStdString(lptr->getElementName()));
		}
	}

	auto owner = element->getOwningElementId();
	if (owner.isValid())
	{
		auto object = owner.openObject();
		if (!object.isNull())
		{
			auto parentElement = OdBmElement::cast(object);
			if (!parentElement.isNull())
				return getLevel(parentElement, name);
		}
	}

	return name;
}

void VectorizeView::fillMeshData(const OdGiDrawable* pDrawable)
{
	OdBmElementPtr element = OdBmElement::cast(pDrawable);
	if (element.isNull())
		return;

	if (!element->isDBRO())
		return;

	std::string elementName = getElementName(element, meshesCount);

	collector->setNextMeshName(elementName);
	collector->setMeshGroup(elementName);

	try
	{
		collector->setCurrentMeta(fillMetadata(element));
	}
	catch(OdError& er)
	{
		//..Hotfix: handle nullPtr exception (need to check updated library)
	}

	meshesCount++;

	std::string layerName = getLevel(element, "Layer Default");
	collector->setLayer(layerName);
}

std::pair<std::vector<std::string>, std::vector<std::string>> VectorizeView::fillMetadata(OdBmElementPtr element)
{
	std::pair<std::vector<std::string>, std::vector<std::string>> metadata;

	OdBuiltInParamArray aParams;
	element->getListParams(aParams);

	OdBmLabelUtilsPEPtr labelUtils = OdBmObject::desc()->getX(OdBmLabelUtilsPE::desc());
	if (labelUtils.isNull())
		return metadata;

	for (OdBuiltInParamArray::iterator it = aParams.begin(); it != aParams.end(); it++)
	{
		std::string builtInName = convertToStdString(OdBm::BuiltInParameter(*it).toString());

		//..Hotfix: handle access violation exception (need to check updated library)
		if (builtInName == std::string("ROOF_SLOPE"))
			continue;

		std::string paramName;
		if (!labelUtils->getLabelFor(*it).isEmpty())
			paramName = convertToStdString(labelUtils->getLabelFor(*it));
		else
			paramName = builtInName;

		OdTfVariant value;
		OdResult res = element->getParam(*it, value);
		if (res == eOk)
		{
			OdBmParamElemPtr pParamElem = element->database()->getObjectId(*it).safeOpenObject();
			OdBmParamDefPtr pDescParam = pParamElem->getParamDef();

			std::string variantValue = variantToString(value, labelUtils, pDescParam, element->getDatabase(), *it);
			if (!variantValue.empty())
			{
				metadata.first.push_back(convertToStdString(pDescParam->getCaption()));
				metadata.second.push_back(variantValue);
			}
		}
	}

	return metadata;
}

void VectorizeView::fillMaterial(const MaterialColors& matColors, repo_material_t& material)
{
	const float norm = 255.f;

	material.shininess = 0.f;
	material.shininessStrength = 0.f;

	material.diffuse = { ODGETRED(matColors.colorDiffuse) / norm, ODGETGREEN(matColors.colorDiffuse) / norm, ODGETBLUE(matColors.colorDiffuse) / norm, 1.0f };
	material.specular = { ODGETRED(matColors.colorSpecular) / norm, ODGETGREEN(matColors.colorSpecular) / norm, ODGETBLUE(matColors.colorSpecular) / norm, 1.0f };
	material.ambient = { ODGETRED(matColors.colorAmbient) / norm, ODGETGREEN(matColors.colorAmbient) / norm, ODGETBLUE(matColors.colorAmbient) / norm, 1.0f };
	material.emissive = { ODGETRED(matColors.colorEmissive) / norm, ODGETGREEN(matColors.colorEmissive) / norm, ODGETBLUE(matColors.colorEmissive) / norm, 1.0f };
}

void VectorizeView::fillTexture(OdDbStub* materialId, repo_material_t& material, bool& missingTexture)
{
	missingTexture = false;

	OdBmObjectId matId(materialId);
	if (!matId.isValid())
		return;

	OdBmObjectPtr materialPtr = matId.safeOpenObject(OdBm::kForRead);
	OdBmMaterialElemPtr materialElem = (OdBmMaterialElem*)(materialPtr.get());
	OdBmMaterialPtr matPtr = materialElem->getMaterial();
	OdBmAssetPtr textureAsset = matPtr->getAsset();

	if (textureAsset.isNull())
		return;

	OdBmAssetPtr bitmapAsset;
	OdString textureFileName;
	OdResult es = OdBmAppearanceAssetHelper::getTextureAsset(textureAsset, bitmapAsset);

	if ((es != OdResult::eOk) || (bitmapAsset.isNull()))
		return;

	OdBmUnifiedBitmapSchemaHelper textureHelper(bitmapAsset);
	es = textureHelper.getTextureFileName(textureFileName);

	if (es != OdResult::eOk)
		return;

	std::string textureName(convertToStdString(textureFileName));
	std::string validTextureName = extractValidTexturePath(textureName);

	if (validTextureName.empty() && !textureName.empty())
		missingTexture = true;

	material.texturePath = validTextureName;
}<|endoftext|>