<commit_before>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/

#ifndef DTK_DETAILS_TREE_CONSTRUCTION_DECL_HPP
#define DTK_DETAILS_TREE_CONSTRUCTION_DECL_HPP

#include "DTK_ConfigDefs.hpp"

#include <DTK_Box.hpp>
#include <DTK_DetailsAlgorithms.hpp> // expand
#include <DTK_DetailsMortonCode.hpp> // morton3D
#include <DTK_DetailsNode.hpp>
#include <DTK_DetailsTags.hpp>
#include <DTK_KokkosHelpers.hpp> // clz

#include <Kokkos_Macros.hpp>
#include <Kokkos_Pair.hpp>
#include <Kokkos_Parallel.hpp>
#include <Kokkos_View.hpp>

namespace DataTransferKit
{
namespace Details
{
/**
 * This structure contains all the functions used to build the BVH. All the
 * functions are static.
 */
template <typename DeviceType>
struct TreeConstruction
{
  public:
    using ExecutionSpace = typename DeviceType::execution_space;

    template <typename Primitives>
    static void calculateBoundingBoxOfTheScene( Primitives primitives,
                                                Box &scene_bounding_box );

    // to assign the Morton code for a given object, we use the centroid point
    // of its bounding box, and express it relative to the bounding box of the
    // scene.
    template <typename Primitives>
    static void
    assignMortonCodes( Primitives primitives,
                       Kokkos::View<unsigned int *, DeviceType> morton_codes,
                       Box const &scene_bounding_box );

    template <typename Primitives>
    static void initializeLeafNodes(
        Primitives primitives,
        Kokkos::View<size_t const *, DeviceType> permutation_indices,
        Kokkos::View<Node *, DeviceType> leaf_nodes );

    static Node *generateHierarchy(
        Kokkos::View<unsigned int *, DeviceType> sorted_morton_codes,
        Kokkos::View<Node *, DeviceType> leaf_nodes,
        Kokkos::View<Node *, DeviceType> internal_nodes,
        Kokkos::View<int *, DeviceType> parents );

    static void calculateInternalNodesBoundingVolumes(
        Kokkos::View<Node const *, DeviceType> leaf_nodes,
        Kokkos::View<Node *, DeviceType> internal_nodes,
        Kokkos::View<int const *, DeviceType> parents );

    KOKKOS_INLINE_FUNCTION
    static int
    commonPrefix( Kokkos::View<unsigned int *, DeviceType> morton_codes, int i,
                  int j )
    {
        using KokkosHelpers::clz;

        int const n = morton_codes.extent( 0 );
        if ( j < 0 || j > n - 1 )
            return -1;

        // our construction algorithm relies on keys being unique so we handle
        // explicitly case of duplicate Morton codes by augmenting each key by
        // a bit representation of its index.
        if ( morton_codes[i] == morton_codes[j] )
        {
            // clz( k[i] ^ k[j] ) == 32
            return 32 + clz( i ^ j );
        }
        return clz( morton_codes[i] ^ morton_codes[j] );
    }

    KOKKOS_FUNCTION
    static int
    findSplit( Kokkos::View<unsigned int *, DeviceType> sorted_morton_codes,
               int first, int last );

    KOKKOS_FUNCTION
    static Kokkos::pair<int, int> determineRange(
        Kokkos::View<unsigned int *, DeviceType> sorted_morton_codes, int i );
};

template <typename ViewType>
class CalculateBoundingBoxOfTheSceneFunctor
{
  public:
    CalculateBoundingBoxOfTheSceneFunctor(
        typename ViewType::const_type primitives )
        : _primitives( primitives )
    {
    }

    KOKKOS_INLINE_FUNCTION
    void init( Box &box ) const { box = Box(); }

    KOKKOS_INLINE_FUNCTION
    void operator()( int const i, Box &box ) const
    {
        expand( box, _primitives( i ) );
    }

    KOKKOS_INLINE_FUNCTION
    void join( volatile Box &dst, volatile Box const &src ) const
    {
        expand( dst, src );
    }

  private:
    typename ViewType::const_type _primitives;
};

template <typename DeviceType>
template <typename Primitives>
inline void TreeConstruction<DeviceType>::calculateBoundingBoxOfTheScene(
    Primitives primitives, Box &scene_bounding_box )
{
    static_assert( Kokkos::is_view<Primitives>::value, "Must pass a view" );
    static_assert( std::is_same<typename Primitives::traits::device_type,
                                DeviceType>::value,
                   "Wrong device type" );
    // TODO static_assert( is_expandable_v<Box, typename
    // Primitives::value_type), "");
    auto const n = primitives.extent( 0 );
    Kokkos::parallel_reduce(
        DTK_MARK_REGION( "calculate_bounding_box_of_the_scene" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ),
        CalculateBoundingBoxOfTheSceneFunctor<decltype( primitives )>(
            primitives ),
        scene_bounding_box );
    Kokkos::fence();
}

template <typename Primitives, typename MortonCodes>
inline void assignMortonCodesDispatch( BoxTag, Primitives primitives,
                                       MortonCodes morton_codes,
                                       Box const &scene_bounding_box )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = morton_codes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "assign_morton_codes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            Point xyz;
            centroid( primitives( i ), xyz );
            translateAndScale( xyz, xyz, scene_bounding_box );
            morton_codes( i ) = morton3D( xyz[0], xyz[1], xyz[2] );
        } );
    Kokkos::fence();
}

template <typename Primitives, typename MortonCodes>
inline void assignMortonCodesDispatch( PointTag, Primitives primitives,
                                       MortonCodes morton_codes,
                                       Box const &scene_bounding_box )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = morton_codes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "assign_morton_codes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            Point xyz;
            translateAndScale( primitives( i ), xyz, scene_bounding_box );
            morton_codes( i ) = morton3D( xyz[0], xyz[1], xyz[2] );
        } );
    Kokkos::fence();
}

template <typename DeviceType>
template <typename Primitives>
inline void TreeConstruction<DeviceType>::assignMortonCodes(
    Primitives primitives,
    Kokkos::View<unsigned int *, DeviceType> morton_codes,
    Box const &scene_bounding_box )
{
    auto const n = primitives.extent( 0 );
    DTK_REQUIRE( morton_codes.extent( 0 ) == n );

    using Tag = typename Tag<typename decltype(
        primitives )::traits::non_const_value_type>::type;
    assignMortonCodesDispatch( Tag{}, primitives, morton_codes,
                               scene_bounding_box );
}

template <typename Primitives, typename Indices, typename Nodes>
inline void initializeLeafNodesDispatch( BoxTag, Primitives primitives,
                                         Indices permutation_indices,
                                         Nodes leaf_nodes )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = leaf_nodes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "initialize_leaf_nodes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            leaf_nodes( i ) = {
                {nullptr, reinterpret_cast<Node *>( permutation_indices( i ) )},
                primitives( permutation_indices( i ) )};
        } );
    Kokkos::fence();
}

template <typename Primitives, typename Indices, typename Nodes>
inline void initializeLeafNodesDispatch( PointTag, Primitives primitives,
                                         Indices permutation_indices,
                                         Nodes leaf_nodes )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = leaf_nodes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "initialize_leaf_nodes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            leaf_nodes( i ) = {
                {nullptr, reinterpret_cast<Node *>( permutation_indices( i ) )},
                {primitives( permutation_indices( i ) ),
                 primitives( permutation_indices( i ) )}};
        } );
    Kokkos::fence();
}

template <typename DeviceType>
template <typename Primitives>
inline void TreeConstruction<DeviceType>::initializeLeafNodes(
    Primitives primitives,
    Kokkos::View<size_t const *, DeviceType> permutation_indices,
    Kokkos::View<Node *, DeviceType> leaf_nodes )
{
    auto const n = leaf_nodes.extent( 0 );
    DTK_REQUIRE( permutation_indices.extent( 0 ) == n );
    DTK_REQUIRE( primitives.extent( 0 ) == n );

    static_assert( sizeof( typename decltype(
                       permutation_indices )::value_type ) == sizeof( Node * ),
                   "Encoding leaf index in pointer to child is not safe if the "
                   "index and pointer types do not have the same size" );

    using Tag = typename Tag<typename decltype(
        primitives )::traits::non_const_value_type>::type;
    initializeLeafNodesDispatch( Tag{}, primitives, permutation_indices,
                                 leaf_nodes );
}

} // namespace Details
} // namespace DataTransferKit

#endif
<commit_msg>Pass primitives by const reference<commit_after>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/

#ifndef DTK_DETAILS_TREE_CONSTRUCTION_DECL_HPP
#define DTK_DETAILS_TREE_CONSTRUCTION_DECL_HPP

#include "DTK_ConfigDefs.hpp"

#include <DTK_Box.hpp>
#include <DTK_DetailsAlgorithms.hpp> // expand
#include <DTK_DetailsMortonCode.hpp> // morton3D
#include <DTK_DetailsNode.hpp>
#include <DTK_DetailsTags.hpp>
#include <DTK_KokkosHelpers.hpp> // clz

#include <Kokkos_Macros.hpp>
#include <Kokkos_Pair.hpp>
#include <Kokkos_Parallel.hpp>
#include <Kokkos_View.hpp>

namespace DataTransferKit
{
namespace Details
{
/**
 * This structure contains all the functions used to build the BVH. All the
 * functions are static.
 */
template <typename DeviceType>
struct TreeConstruction
{
  public:
    using ExecutionSpace = typename DeviceType::execution_space;

    template <typename Primitives>
    static void calculateBoundingBoxOfTheScene( Primitives const &primitives,
                                                Box &scene_bounding_box );

    // to assign the Morton code for a given object, we use the centroid point
    // of its bounding box, and express it relative to the bounding box of the
    // scene.
    template <typename Primitives>
    static void
    assignMortonCodes( Primitives const &primitives,
                       Kokkos::View<unsigned int *, DeviceType> morton_codes,
                       Box const &scene_bounding_box );

    template <typename Primitives>
    static void initializeLeafNodes(
        Primitives const &primitives,
        Kokkos::View<size_t const *, DeviceType> permutation_indices,
        Kokkos::View<Node *, DeviceType> leaf_nodes );

    static Node *generateHierarchy(
        Kokkos::View<unsigned int *, DeviceType> sorted_morton_codes,
        Kokkos::View<Node *, DeviceType> leaf_nodes,
        Kokkos::View<Node *, DeviceType> internal_nodes,
        Kokkos::View<int *, DeviceType> parents );

    static void calculateInternalNodesBoundingVolumes(
        Kokkos::View<Node const *, DeviceType> leaf_nodes,
        Kokkos::View<Node *, DeviceType> internal_nodes,
        Kokkos::View<int const *, DeviceType> parents );

    KOKKOS_INLINE_FUNCTION
    static int
    commonPrefix( Kokkos::View<unsigned int *, DeviceType> morton_codes, int i,
                  int j )
    {
        using KokkosHelpers::clz;

        int const n = morton_codes.extent( 0 );
        if ( j < 0 || j > n - 1 )
            return -1;

        // our construction algorithm relies on keys being unique so we handle
        // explicitly case of duplicate Morton codes by augmenting each key by
        // a bit representation of its index.
        if ( morton_codes[i] == morton_codes[j] )
        {
            // clz( k[i] ^ k[j] ) == 32
            return 32 + clz( i ^ j );
        }
        return clz( morton_codes[i] ^ morton_codes[j] );
    }

    KOKKOS_FUNCTION
    static int
    findSplit( Kokkos::View<unsigned int *, DeviceType> sorted_morton_codes,
               int first, int last );

    KOKKOS_FUNCTION
    static Kokkos::pair<int, int> determineRange(
        Kokkos::View<unsigned int *, DeviceType> sorted_morton_codes, int i );
};

template <typename ViewType>
class CalculateBoundingBoxOfTheSceneFunctor
{
  public:
    CalculateBoundingBoxOfTheSceneFunctor(
        typename ViewType::const_type primitives )
        : _primitives( primitives )
    {
    }

    KOKKOS_INLINE_FUNCTION
    void init( Box &box ) const { box = Box(); }

    KOKKOS_INLINE_FUNCTION
    void operator()( int const i, Box &box ) const
    {
        expand( box, _primitives( i ) );
    }

    KOKKOS_INLINE_FUNCTION
    void join( volatile Box &dst, volatile Box const &src ) const
    {
        expand( dst, src );
    }

  private:
    typename ViewType::const_type _primitives;
};

template <typename DeviceType>
template <typename Primitives>
inline void TreeConstruction<DeviceType>::calculateBoundingBoxOfTheScene(
    Primitives const &primitives, Box &scene_bounding_box )
{
    static_assert( Kokkos::is_view<Primitives>::value, "Must pass a view" );
    static_assert( std::is_same<typename Primitives::traits::device_type,
                                DeviceType>::value,
                   "Wrong device type" );
    // TODO static_assert( is_expandable_v<Box, typename
    // Primitives::value_type), "");
    auto const n = primitives.extent( 0 );
    Kokkos::parallel_reduce(
        DTK_MARK_REGION( "calculate_bounding_box_of_the_scene" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ),
        CalculateBoundingBoxOfTheSceneFunctor<decltype( primitives )>(
            primitives ),
        scene_bounding_box );
    Kokkos::fence();
}

template <typename Primitives, typename MortonCodes>
inline void assignMortonCodesDispatch( BoxTag, Primitives const &primitives,
                                       MortonCodes morton_codes,
                                       Box const &scene_bounding_box )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = morton_codes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "assign_morton_codes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            Point xyz;
            centroid( primitives( i ), xyz );
            translateAndScale( xyz, xyz, scene_bounding_box );
            morton_codes( i ) = morton3D( xyz[0], xyz[1], xyz[2] );
        } );
    Kokkos::fence();
}

template <typename Primitives, typename MortonCodes>
inline void assignMortonCodesDispatch( PointTag, Primitives const &primitives,
                                       MortonCodes morton_codes,
                                       Box const &scene_bounding_box )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = morton_codes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "assign_morton_codes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            Point xyz;
            translateAndScale( primitives( i ), xyz, scene_bounding_box );
            morton_codes( i ) = morton3D( xyz[0], xyz[1], xyz[2] );
        } );
    Kokkos::fence();
}

template <typename DeviceType>
template <typename Primitives>
inline void TreeConstruction<DeviceType>::assignMortonCodes(
    Primitives const &primitives,
    Kokkos::View<unsigned int *, DeviceType> morton_codes,
    Box const &scene_bounding_box )
{
    auto const n = primitives.extent( 0 );
    DTK_REQUIRE( morton_codes.extent( 0 ) == n );

    using Tag = typename Tag<typename decltype(
        primitives )::traits::non_const_value_type>::type;
    assignMortonCodesDispatch( Tag{}, primitives, morton_codes,
                               scene_bounding_box );
}

template <typename Primitives, typename Indices, typename Nodes>
inline void initializeLeafNodesDispatch( BoxTag, Primitives const &primitives,
                                         Indices permutation_indices,
                                         Nodes leaf_nodes )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = leaf_nodes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "initialize_leaf_nodes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            leaf_nodes( i ) = {
                {nullptr, reinterpret_cast<Node *>( permutation_indices( i ) )},
                primitives( permutation_indices( i ) )};
        } );
    Kokkos::fence();
}

template <typename Primitives, typename Indices, typename Nodes>
inline void initializeLeafNodesDispatch( PointTag, Primitives const &primitives,
                                         Indices permutation_indices,
                                         Nodes leaf_nodes )
{
    using ExecutionSpace =
        typename decltype( primitives )::traits::execution_space;
    auto const n = leaf_nodes.extent( 0 );
    Kokkos::parallel_for(
        DTK_MARK_REGION( "initialize_leaf_nodes" ),
        Kokkos::RangePolicy<ExecutionSpace>( 0, n ), KOKKOS_LAMBDA( int i ) {
            leaf_nodes( i ) = {
                {nullptr, reinterpret_cast<Node *>( permutation_indices( i ) )},
                {primitives( permutation_indices( i ) ),
                 primitives( permutation_indices( i ) )}};
        } );
    Kokkos::fence();
}

template <typename DeviceType>
template <typename Primitives>
inline void TreeConstruction<DeviceType>::initializeLeafNodes(
    Primitives const &primitives,
    Kokkos::View<size_t const *, DeviceType> permutation_indices,
    Kokkos::View<Node *, DeviceType> leaf_nodes )
{
    auto const n = leaf_nodes.extent( 0 );
    DTK_REQUIRE( permutation_indices.extent( 0 ) == n );
    DTK_REQUIRE( primitives.extent( 0 ) == n );

    static_assert( sizeof( typename decltype(
                       permutation_indices )::value_type ) == sizeof( Node * ),
                   "Encoding leaf index in pointer to child is not safe if the "
                   "index and pointer types do not have the same size" );

    using Tag = typename Tag<typename decltype(
        primitives )::traits::non_const_value_type>::type;
    initializeLeafNodesDispatch( Tag{}, primitives, permutation_indices,
                                 leaf_nodes );
}

} // namespace Details
} // namespace DataTransferKit

#endif
<|endoftext|>


<commit_before>/// @file
/// @copyright The code is licensed under the BSD License
///            <http://opensource.org/licenses/BSD-2-Clause>,
///            Copyright (c) 2013-2015 Alexandre Hamez.
/// @author Alexandre Hamez

#include <cassert>
#include <iostream>

#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/algorithm/for_each.hpp>

#include "mc/classic/count_tokens.hh"
#include "mc/classic/dead_states.hh"
#include "mc/classic/firing_rule.hh"
#include "mc/classic/make_order.hh"
#include "mc/classic/path_to.hh"
#include "mc/classic/reachability.hh"
#include "mc/classic/sdd.hh"
#include "mc/classic/threads.hh"
#include "classic.hh"
#include "mc/shared/exceptions.hh"
#include "mc/shared/export.hh"
#include "mc/shared/results.hh"
#include "mc/shared/statistics.hh"
#include "mc/shared/step.hh"
#include "support/pn/constants.hh"
#include "support/util/timer.hh"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

namespace pnmc { namespace mc { namespace classic {

/*------------------------------------------------------------------------------------------------*/

namespace /* unnamed */ {

SDD
initial_state(const sdd::order<sdd_conf>& order, const pn::net& net)
{
  auto timed = std::map<std::string, std::reference_wrapper<const pn::transition>>{};
  boost::range::for_each( net.transitions()
                        , [&](const auto& t){if (t.timed()) timed.emplace(t.name, t);});

  return {order, [&](const auto& id)
                    {
                      const auto cit = net.places().find(id);
                      if (cit != end(net.places()))
                      {
                        return flat_set{cit->marking};
                      }
                      else
                      {
                        const auto t_cit = timed.find(id);
                        assert(t_cit != timed.end());
                        return net.enabled(t_cit->second.get().name)
                             ? flat_set{0}
                             : flat_set{pn::sharp};
                      }}};
}

} // namespace unnamed

/*------------------------------------------------------------------------------------------------*/

void
classic::operator()(const pn::net& net, const properties::formulae& formulae)
{
  if (not formulae.fireable_transitions.empty())
  {
    conf.compute_dead_transitions = true;
  }
  if (formulae.compute_deadlock)
  {
    conf.compute_dead_states = true;
  }
  if (conf.compute_dead_states and net.timed())
  {
    std::cerr << "Computation of dead states for Time Petri Nets is not supported yet.\n";
    conf.compute_dead_states = false;
  }
  if (conf.trace and net.timed())
  {
    std::cerr << "Computation of a trace for Time Petri Nets is not supported yet.\n";
    conf.trace = false;
  }

  using conf::filename;
  using dot_sdd = shared::dot_sdd<sdd_conf>;

  auto total_timer = util::timer{};

  // Configure libsdd.
  sdd_conf sconf;
  sconf.sdd_unique_table_size = conf.ut_sizes.at("sdd");
  sconf.sdd_difference_cache_size = conf.cache_sizes.at("diff");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("inter");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("sum");
  sconf.hom_unique_table_size = conf.ut_sizes.at("hom");
  sconf.hom_cache_size = conf.cache_sizes.at("hom");

  // This pointer WILL NOT be deleted to avoid a too long shutdown time due to big hash table
  // cleanups.
  auto manager_ptr = new sdd::manager<sdd_conf>{sdd::init(sconf)};
  auto& manager = *manager_ptr;

  auto stats = statistics{};
  stats.max_time = conf.max_time;
  if (conf.stats_conf.count(shared::stats::pn))
  {
    stats.pn_statistics = pn::statistics(net);
  }
  auto res = results{};

  // Set to true by an asynchrous thread when the time limit is reached.
  auto stop_flag = false;

  std::cout << "\n-- Steps\n";

  // Build the order.
  res.order = make_order(conf, stats, net);
  if (res.order->empty())
  {
    throw std::runtime_error("Empty order");
  }
  shared::export_json(conf, filename::json_order, *res.order);

  // Get the initial state.
  res.m0 = initial_state(*res.order, net);

  // Map of live transitions.
  auto live_transitions = boost::dynamic_bitset<>{net.transitions().size()};

  // Compute the transition relation.
  const auto h_operands = [&]
  {
    auto step = shared::step{"firing rule", &stats.relation_duration};
    return firing_rule(conf, *res.order, net, live_transitions, stop_flag);
  }();
  const auto key = [](const auto& kv){return kv.first;}; // Extract keys of a map
  const auto h = fixpoint(sum( *res.order
                             , boost::make_transform_iterator(begin(h_operands), key)
                             , boost::make_transform_iterator(end(h_operands), key)));

  // Rewrite the transition relation.
  const auto h_opt = [&]
  {
    shared::step step("rewrite", &stats.rewrite_duration);
    return sdd::rewrite(*res.order, h);
  }();

  // Compute the state space.
  {
    auto step = shared::step{"state space", &stats.state_space_duration};
    // Threads will be stopped at scope exit.
    threads _{conf, stats, stop_flag, manager, step.timer};
    try
    {
      res.states = h_opt(*res.order, *res.m0);
    }
    catch (const shared::bound_error& e)
    {
      stats.interrupted = true;
      std::cout << "Place " << e.place << " marking >=" << conf.marking_bound << '\n';
    }
    catch (const shared::interrupted&)
    {
      stats.interrupted = true;
      std::cout << "Computation interrupted after " << step.timer.duration().count() << "s\n";
    }
    if (stats.interrupted)
    {
      shared::export_json(conf, filename::json_stats, stats);
      shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
      return;
    }
  }

  if (conf.count_tokens)
  {
    stats.tokens_duration.emplace();
    auto step = shared::step{"count tokens", &*stats.tokens_duration};
    count_tokens(res, *res.states, net);
  }

  if (conf.compute_dead_transitions)
  {
    auto step = shared::step{"dead transitions"};
    res.dead_transitions.emplace();
    for (const auto& t : net.transitions())
    {
      if (not live_transitions[t.uid])
      {
        res.dead_transitions->emplace(t.name);
      }
    }
  }

  if (conf.compute_dead_states)
  {
    {
      stats.dead_states_duration.emplace();
      auto step = shared::step{"dead states", &*stats.dead_states_duration};
      res.dead_states = dead_states(*res.order, net, *res.states);
    }
    if (conf.trace)
    {
      stats.trace_duration.emplace();
      auto step = shared::step{"trace", &*stats.trace_duration};
      res.trace = shortest_path(*res.order, *res.m0, *res.dead_states, net, h_operands);
    }
  }

  if (not formulae.booleans.empty() or not formulae.integers.empty())
  {
    stats.reachability_duration.emplace();
    auto step = shared::step{"reachability", &*stats.reachability_duration};
    reachability(*res.order, formulae, res);
  }

  if (conf.stats_conf.count(shared::stats::final_sdd))
  {
    stats.sdd_statistics = sdd::tools::statistics(*res.states);
  }
  stats.manager_statistics = sdd::tools::statistics(manager);

  stats.total_duration = total_timer.duration();
  std::cout << "total" << std::setw(15) << ": " << stats.total_duration.count() << "s";
  std::cout << "\n\n-- Results\n";
  std::cout << res;

  shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
  shared::export_dot(conf, filename::dot_m0, dot_sdd{*res.m0, *res.order});
  shared::export_dot(conf, filename::dot_final, dot_sdd{*res.states, *res.order});
  shared::export_json(conf, filename::json_stats, stats);
  shared::export_json(conf, filename::json_results, res);
  shared::export_json(conf, filename::json_h, h, filename::json_h_opt, h_opt);
}

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::classic

#pragma GCC diagnostic pop
<commit_msg>TPN: compute dead states<commit_after>/// @file
/// @copyright The code is licensed under the BSD License
///            <http://opensource.org/licenses/BSD-2-Clause>,
///            Copyright (c) 2013-2015 Alexandre Hamez.
/// @author Alexandre Hamez

#include <cassert>
#include <iostream>

#include <boost/iterator/transform_iterator.hpp>
#include <boost/range/algorithm/for_each.hpp>

#include "mc/classic/count_tokens.hh"
#include "mc/classic/dead_states.hh"
#include "mc/classic/firing_rule.hh"
#include "mc/classic/make_order.hh"
#include "mc/classic/path_to.hh"
#include "mc/classic/reachability.hh"
#include "mc/classic/sdd.hh"
#include "mc/classic/threads.hh"
#include "classic.hh"
#include "mc/shared/exceptions.hh"
#include "mc/shared/export.hh"
#include "mc/shared/results.hh"
#include "mc/shared/statistics.hh"
#include "mc/shared/step.hh"
#include "support/pn/constants.hh"
#include "support/util/timer.hh"

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

namespace pnmc { namespace mc { namespace classic {

/*------------------------------------------------------------------------------------------------*/

namespace /* unnamed */ {

SDD
initial_state(const sdd::order<sdd_conf>& order, const pn::net& net)
{
  auto timed = std::map<std::string, std::reference_wrapper<const pn::transition>>{};
  boost::range::for_each( net.transitions()
                        , [&](const auto& t){if (t.timed()) timed.emplace(t.name, t);});

  return {order, [&](const auto& id)
                    {
                      const auto cit = net.places().find(id);
                      if (cit != end(net.places()))
                      {
                        return flat_set{cit->marking};
                      }
                      else
                      {
                        const auto t_cit = timed.find(id);
                        assert(t_cit != timed.end());
                        return net.enabled(t_cit->second.get().name)
                             ? flat_set{0}
                             : flat_set{pn::sharp};
                      }}};
}

} // namespace unnamed

/*------------------------------------------------------------------------------------------------*/

void
classic::operator()(const pn::net& net, const properties::formulae& formulae)
{
  if (not formulae.fireable_transitions.empty())
  {
    conf.compute_dead_transitions = true;
  }
  if (formulae.compute_deadlock)
  {
    conf.compute_dead_states = true;
  }
  if (conf.trace and net.timed())
  {
    std::cerr << "Computation of a trace for Time Petri Nets is not supported yet.\n";
    conf.trace = false;
  }

  using conf::filename;
  using dot_sdd = shared::dot_sdd<sdd_conf>;

  auto total_timer = util::timer{};

  // Configure libsdd.
  sdd_conf sconf;
  sconf.sdd_unique_table_size = conf.ut_sizes.at("sdd");
  sconf.sdd_difference_cache_size = conf.cache_sizes.at("diff");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("inter");
  sconf.sdd_intersection_cache_size = conf.cache_sizes.at("sum");
  sconf.hom_unique_table_size = conf.ut_sizes.at("hom");
  sconf.hom_cache_size = conf.cache_sizes.at("hom");

  // This pointer WILL NOT be deleted to avoid a too long shutdown time due to big hash table
  // cleanups.
  auto manager_ptr = new sdd::manager<sdd_conf>{sdd::init(sconf)};
  auto& manager = *manager_ptr;

  auto stats = statistics{};
  stats.max_time = conf.max_time;
  if (conf.stats_conf.count(shared::stats::pn))
  {
    stats.pn_statistics = pn::statistics(net);
  }
  auto res = results{};

  // Set to true by an asynchrous thread when the time limit is reached.
  auto stop_flag = false;

  std::cout << "\n-- Steps\n";

  // Build the order.
  res.order = make_order(conf, stats, net);
  if (res.order->empty())
  {
    throw std::runtime_error("Empty order");
  }
  shared::export_json(conf, filename::json_order, *res.order);

  // Get the initial state.
  res.m0 = initial_state(*res.order, net);

  // Map of live transitions.
  auto live_transitions = boost::dynamic_bitset<>{net.transitions().size()};

  // Compute the transition relation.
  const auto h_operands = [&]
  {
    auto step = shared::step{"firing rule", &stats.relation_duration};
    return firing_rule(conf, *res.order, net, live_transitions, stop_flag);
  }();
  const auto key = [](const auto& kv){return kv.first;}; // Extract keys of a map
  const auto h = fixpoint(sum( *res.order
                             , boost::make_transform_iterator(begin(h_operands), key)
                             , boost::make_transform_iterator(end(h_operands), key)));

  // Rewrite the transition relation.
  const auto h_opt = [&]
  {
    shared::step step("rewrite", &stats.rewrite_duration);
    return sdd::rewrite(*res.order, h);
  }();

  // Compute the state space.
  {
    auto step = shared::step{"state space", &stats.state_space_duration};
    // Threads will be stopped at scope exit.
    threads _{conf, stats, stop_flag, manager, step.timer};
    try
    {
      res.states = h_opt(*res.order, *res.m0);
    }
    catch (const shared::bound_error& e)
    {
      stats.interrupted = true;
      std::cout << "Place " << e.place << " marking >=" << conf.marking_bound << '\n';
    }
    catch (const shared::interrupted&)
    {
      stats.interrupted = true;
      std::cout << "Computation interrupted after " << step.timer.duration().count() << "s\n";
    }
    if (stats.interrupted)
    {
      shared::export_json(conf, filename::json_stats, stats);
      shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
      return;
    }
  }

  if (conf.count_tokens)
  {
    stats.tokens_duration.emplace();
    auto step = shared::step{"count tokens", &*stats.tokens_duration};
    count_tokens(res, *res.states, net);
  }

  if (conf.compute_dead_transitions)
  {
    auto step = shared::step{"dead transitions"};
    res.dead_transitions.emplace();
    for (const auto& t : net.transitions())
    {
      if (not live_transitions[t.uid])
      {
        res.dead_transitions->emplace(t.name);
      }
    }
  }

  if (conf.compute_dead_states)
  {
    {
      stats.dead_states_duration.emplace();
      auto step = shared::step{"dead states", &*stats.dead_states_duration};
      res.dead_states = dead_states(*res.order, net, *res.states);
    }
    if (conf.trace)
    {
      stats.trace_duration.emplace();
      auto step = shared::step{"trace", &*stats.trace_duration};
      res.trace = shortest_path(*res.order, *res.m0, *res.dead_states, net, h_operands);
    }
  }

  if (not formulae.booleans.empty() or not formulae.integers.empty())
  {
    stats.reachability_duration.emplace();
    auto step = shared::step{"reachability", &*stats.reachability_duration};
    reachability(*res.order, formulae, res);
  }

  if (conf.stats_conf.count(shared::stats::final_sdd))
  {
    stats.sdd_statistics = sdd::tools::statistics(*res.states);
  }
  stats.manager_statistics = sdd::tools::statistics(manager);

  stats.total_duration = total_timer.duration();
  std::cout << "total" << std::setw(15) << ": " << stats.total_duration.count() << "s";
  std::cout << "\n\n-- Results\n";
  std::cout << res;

  shared::export_dot(conf, filename::dot_h, h, filename::dot_h_opt, h_opt);
  shared::export_dot(conf, filename::dot_m0, dot_sdd{*res.m0, *res.order});
  shared::export_dot(conf, filename::dot_final, dot_sdd{*res.states, *res.order});
  shared::export_json(conf, filename::json_stats, stats);
  shared::export_json(conf, filename::json_results, res);
  shared::export_json(conf, filename::json_h, h, filename::json_h_opt, h_opt);
}

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::classic

#pragma GCC diagnostic pop
<|endoftext|>


<commit_before>/*
 * Win32GLRenderContext.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "../../GLRenderContext.h"
#include "../../GLExtensions.h"
#include "../../GLExtensionLoader.h"
#include <LLGL/Platform/NativeHandle.h>
#include <LLGL/Log.h>
#include <algorithm>

namespace LLGL
{

void GLRenderContext::Present()
{
    SwapBuffers(context_.hDC);
}

bool GLRenderContext::GLMakeCurrent(GLRenderContext* renderContext)
{
    if (renderContext)
    {
        /* Update new active state manager */
        GLStateManager::active = renderContext->stateMngr_.get();

        /* Make this OpenGL context to the current one */
        const auto& ctx = renderContext->context_;
        return (wglMakeCurrent(ctx.hDC, ctx.hGLRC) == TRUE);
    }
    else
        return (wglMakeCurrent(0, 0) == TRUE);
}

/*
 * ======= Private: =======
 */

static void ErrAntiAliasingNotSupported()
{
    Log::StdErr() << "multi-sample anti-aliasing is not supported" << std::endl;
}

void GLRenderContext::GetNativeContextHandle(NativeContextHandle& windowContext)
{
    // do nothing for Win32
}

/*
TODO:
- When anti-aliasing and extended-profile-selection is enabled,
  maximal 2 contexts should be created (and not 3).
*/
void GLRenderContext::CreateContext(GLRenderContext* sharedRenderContext)
{
    /* If a shared context has passed, use its pre-selected pixel format */
    if (desc_.antiAliasing.enabled && sharedRenderContext)
        CopyPixelFormat(*sharedRenderContext);

    /* First setup device context and choose pixel format */
    SetupDeviceContextAndPixelFormat();

    /* Create standard render context first */
    auto stdRenderContext = CreateGLContext(false, sharedRenderContext);

    if (!stdRenderContext)
        throw std::runtime_error("failed to create standard OpenGL render context");

    /* Check for multi-sample anti-aliasing */
    if (desc_.antiAliasing.enabled && !hasSharedContext_)
    {
        /* Setup anti-aliasing after creating a standard render context. */
        if (SetupAntiAliasing())
        {
            /* Delete old standard render context */
            DeleteGLContext(stdRenderContext);

            /*
            For anti-aliasing we must recreate the window,
            because a pixel format can be choosen only once for a Win32 window,
            then update device context and pixel format
            */
            RecreateWindow();

            /* Create a new render context -> now with anti-aliasing pixel format */
            stdRenderContext = CreateGLContext(false, sharedRenderContext);

            if (!stdRenderContext)
                Log::StdErr() << "failed to create multi-sample anti-aliasing" << std::endl;
        }
        else
        {
            /* Print warning and disable anti-aliasing */
            ErrAntiAliasingNotSupported();

            desc_.antiAliasing.enabled = false;
            desc_.antiAliasing.samples = 0;
        }
    }

    context_.hGLRC = stdRenderContext;

    /* Check for extended render context */
    if (desc_.profileOpenGL.extProfile && !hasSharedContext_)
    {
        /*
        Load profile selection extension (wglCreateContextAttribsARB) via current context,
        then create new context with extended settings.
        */
        if (wglCreateContextAttribsARB || LoadCreateContextProcs())
        {
            auto extRenderContext = CreateGLContext(true, sharedRenderContext);

            if (extRenderContext)
            {
                /* Use the extended profile and delete the old standard render context */
                context_.hGLRC = extRenderContext;
                DeleteGLContext(stdRenderContext);
            }
            else
            {
                /* Print warning and disbale profile selection */
                Log::StdErr() << "failed to create extended OpenGL profile" << std::endl;
                desc_.profileOpenGL.extProfile = false;
            }
        }
        else
        {
            /* Print warning and disable profile settings */
            Log::StdErr() << "failed to select OpenGL profile" << std::endl;
            desc_.profileOpenGL.extProfile = false;
        }
    }

    /* Check if context creation was successful */
    if (!context_.hGLRC)
        throw std::runtime_error("failed to create OpenGL render context");

    if (wglMakeCurrent(context_.hDC, context_.hGLRC) != TRUE)
        throw std::runtime_error("failed to activate OpenGL render context");

    /*
    Share resources with previous render context (only for compatibility profile).
    -> Only do this, if this context has its own GL hardware context (hasSharedContext_ == false),
       but a shared render context was passed (sharedRenderContext != null).
    */
    if (sharedRenderContext && !hasSharedContext_ && !desc_.profileOpenGL.extProfile)
    {
        if (!wglShareLists(sharedRenderContext->context_.hGLRC, context_.hGLRC))
            throw std::runtime_error("failed to share resources from OpenGL render context");
    }

    /* Query GL version of final render context */
    //QueryGLVersion();

    /* Setup v-sync interval */
    SetupVSyncInterval();
}

void GLRenderContext::DeleteContext()
{
    if (!hasSharedContext_)
    {
        /* Deactivate context before deletion */
        //Deactivate();
        DeleteGLContext(context_.hGLRC);
    }
}

void GLRenderContext::DeleteGLContext(HGLRC& renderContext)
{
    /* Delete GL render context */
    if (!wglDeleteContext(renderContext))
        Log::StdErr() << "failed to delete OpenGL render context" << std::endl;
    else
        renderContext = 0;
}

HGLRC GLRenderContext::CreateGLContext(bool useExtProfile, GLRenderContext* sharedRenderContext)
{
    /* Create hardware render context */
    HGLRC renderContext = 0;

    if (!sharedRenderContext || !sharedRenderContext->context_.hGLRC /* || createOwnHardwareContext == true*/)
    {
        /* Create own hardware context */
        hasSharedContext_ = false;

        if (useExtProfile)
        {
            renderContext = CreateExtContextProfile(
                (sharedRenderContext != nullptr ? sharedRenderContext->context_.hGLRC : nullptr)
            );
        }
        else
            renderContext = CreateStdContextProfile();
    }
    else
    {
        /* Use shared render context */
        hasSharedContext_ = true;
        renderContext = sharedRenderContext->context_.hGLRC;
    }

    if (!renderContext)
        return 0;

    /* Activate new render context */
    if (wglMakeCurrent(context_.hDC, renderContext) != TRUE)
    {
        /* Print error and delete unusable render context */
        Log::StdErr() << "failed to active OpenGL render context (wglMakeCurrent)" << std::endl;
        DeleteGLContext(renderContext);
        return 0;
    }

    /* Query GL version of current render context */
    //QueryGLVersion();

    return renderContext;
}

HGLRC GLRenderContext::CreateStdContextProfile()
{
    /* Create OpenGL "Compatibility Profile" render context */
    return wglCreateContext(context_.hDC);
}

static void ConvertGLVersion(const OpenGLVersion version, GLint& major, GLint& minor)
{
    if (version == OpenGLVersion::OpenGL_Latest)
    {
        major = 4;
        minor = 5;
    }
    else
    {
        auto ver = static_cast<int>(version);
        major = ver / 100;
        minor = (ver % 100) / 10;
    }
}

HGLRC GLRenderContext::CreateExtContextProfile(HGLRC sharedGLRC)
{
    bool useCoreProfile = desc_.profileOpenGL.coreProfile;

    /* Initialize GL version number */
    GLint major = 0, minor = 0;
    ConvertGLVersion(desc_.profileOpenGL.version, major, minor);

    /* Setup extended attributes to select the OpenGL profile */
    const int attribList[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB,  major,
        WGL_CONTEXT_MINOR_VERSION_ARB,  minor,
        #ifdef LLGL_DEBUG
        WGL_CONTEXT_FLAGS_ARB,          WGL_CONTEXT_DEBUG_BIT_ARB /*| WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB*/,
        #endif
        WGL_CONTEXT_PROFILE_MASK_ARB,   (useCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB),
        0, 0
    };

    /* Create OpenGL "Core Profile" or "Compatibility Profile" render context */
    HGLRC renderContext = wglCreateContextAttribsARB(context_.hDC, sharedGLRC, attribList);

    /* Check for errors */
    DWORD error = GetLastError();

    if (error == ERROR_INVALID_VERSION_ARB)
        Log::StdErr() << "invalid version for OpenGL profile" << std::endl;
    else if (error == ERROR_INVALID_PROFILE_ARB)
        Log::StdErr() << "invalid OpenGL profile" << std::endl;
    else
        return renderContext;

    return 0;
}

void GLRenderContext::SetupDeviceContextAndPixelFormat()
{
    /* Get device context from window */
    NativeHandle nativeHandle;
    GetWindow().GetNativeHandle(&nativeHandle);
    context_.hDC = GetDC(nativeHandle.window);

    /* Select suitable pixel format */
    SelectPixelFormat();
}

void GLRenderContext::SelectPixelFormat()
{
    /* Setup pixel format attributes */
    const auto colorDepth = static_cast<BYTE>(desc_.videoMode.colorDepth);

    PIXELFORMATDESCRIPTOR formatDesc
    {
        sizeof(PIXELFORMATDESCRIPTOR),  // Structure size
        1,                              // Version number
        ( PFD_DRAW_TO_WINDOW |          // Format must support draw-to-window
          PFD_SUPPORT_OPENGL |          // Format must support OpenGL
          PFD_DOUBLEBUFFER   |          // Must support double buffering
          PFD_SWAP_EXCHANGE ),          // Hint to the driver to exchange the back- with the front buffer
        PFD_TYPE_RGBA,                  // Request an RGBA format
        colorDepth,                     // Select color bit depth (cColorBits)
        0, 0, 0, 0, 0, 0,               // Color bits ignored
        8,                              // Request an alpha buffer of 8 bits (cAlphaBits)
        0,                              // Shift bit ignored
        0,                              // No accumulation buffer
        0, 0, 0, 0,                     // Accumulation bits ignored
        24,                             // Z-Buffer bits (cDepthBits)
        1,                              // Stencil buffer bits (cStencilBits)
        0,                              // No auxiliary buffer
        0,                              // Main drawing layer (No longer used)
        0,                              // Reserved
        0, 0, 0                         // Layer masks ignored
    };

    /* Try to find suitable pixel format */
    const bool wantAntiAliasFormat = (desc_.antiAliasing.enabled && !context_.pixelFormatsMS.empty());

    std::size_t msPixelFormatIndex = 0;
    bool wasStandardFormatUsed = false;

    while (true)
    {
        if (wantAntiAliasFormat && msPixelFormatIndex < GLPlatformContext::maxNumPixelFormatsMS)
        {
            /* Choose anti-aliasing pixel format */
            context_.pixelFormat = context_.pixelFormatsMS[msPixelFormatIndex++];
        }

        if (!context_.pixelFormat)
        {
            /* Choose standard pixel format */
            context_.pixelFormat = ChoosePixelFormat(context_.hDC, &formatDesc);

            if (wantAntiAliasFormat)
                ErrAntiAliasingNotSupported();

            wasStandardFormatUsed = true;
        }

        /* Check for errors */
        if (!context_.pixelFormat)
            throw std::runtime_error("failed to select pixel format");

        /* Set pixel format */
        auto wasFormatSelected = SetPixelFormat(context_.hDC, context_.pixelFormat, &formatDesc);

        if (!wasFormatSelected)
        {
            if (wasStandardFormatUsed)
                throw std::runtime_error("failed to set pixel format");
        }
        else
        {
            /* Format was selected -> quit with success */
            break;
        }
    }
}

bool GLRenderContext::SetupAntiAliasing()
{
    /*
    Load GL extension "wglChoosePixelFormatARB" to choose anti-aliasing pixel formats
    A valid (standard) GL context must be created at this time, before an extension can be loaded!
    */
    if (!wglChoosePixelFormatARB && !LoadPixelFormatProcs())
        return false;

    /* Setup pixel format for anti-aliasing */
    const auto queriedMultiSamples = desc_.antiAliasing.samples;

    while (desc_.antiAliasing.samples > 0)
    {
        float attribsFlt[] = { 0.0f, 0.0f };

        int attribsInt[] =
        {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
            WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB,
            WGL_COLOR_BITS_ARB,     desc_.videoMode.colorDepth,
            WGL_ALPHA_BITS_ARB,     8,
            WGL_DEPTH_BITS_ARB,     24,
            WGL_STENCIL_BITS_ARB,   1,
            WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
            WGL_SAMPLE_BUFFERS_ARB, (desc_.antiAliasing.enabled ? GL_TRUE : GL_FALSE),
            WGL_SAMPLES_ARB,        static_cast<int>(desc_.antiAliasing.samples),
            0, 0
        };

        /* Choose new pixel format with anti-aliasing */
        UINT numFormats = 0;

        context_.pixelFormatsMS.resize(GLPlatformContext::maxNumPixelFormatsMS);

        int result = wglChoosePixelFormatARB(
            context_.hDC,
            attribsInt,
            attribsFlt,
            GLPlatformContext::maxNumPixelFormatsMS,
            context_.pixelFormatsMS.data(),
            &numFormats
        );

        context_.pixelFormatsMS.resize(numFormats);

        if (!result || numFormats < 1)
        {
            if (desc_.antiAliasing.samples <= 0)
            {
                /* Lowest count of multi-samples reached -> return with error */
                return false;
            }

            /* Choose next lower count of multi-samples */
            --desc_.antiAliasing.samples;
        }
        else
        {
            /* Found suitable pixel formats */
            break;
        }
    }

    /* Check if multi-sample count was reduced */
    if (desc_.antiAliasing.samples < queriedMultiSamples)
    {
        Log::StdOut()
            << "reduced multi-samples for anti-aliasing from "
            << std::to_string(queriedMultiSamples) << " to "
            << std::to_string(desc_.antiAliasing.samples) << std::endl;
    }

    /* Enable anti-aliasing */
    if (desc_.antiAliasing.enabled)
        glEnable(GL_MULTISAMPLE);
    else
        glDisable(GL_MULTISAMPLE);

    return true;
}

void GLRenderContext::CopyPixelFormat(GLRenderContext& sourceContext)
{
    context_.pixelFormat    = sourceContext.context_.pixelFormat;
    context_.pixelFormatsMS = sourceContext.context_.pixelFormatsMS;
}

bool GLRenderContext::SetupVSyncInterval()
{
    /* Load GL extension "wglSwapIntervalEXT" to set v-sync interval */
    if (wglSwapIntervalEXT || LoadSwapIntervalProcs())
    {
        /* Setup v-sync interval */
        int interval = (desc_.vsync.enabled ? static_cast<int>(desc_.vsync.interval) : 0);
        wglSwapIntervalEXT(interval);
        return true;
    }
    return false;
}

void GLRenderContext::RecreateWindow()
{
    /* Recreate window with current descriptor, then update device context and pixel format */
    GetWindow().Recreate(GetWindow().QueryDesc());
    SetupDeviceContextAndPixelFormat();
}

} // /namespace LLGL

// ================================================================================
<commit_msg>Bug fix.<commit_after>/*
 * Win32GLRenderContext.cpp
 *
 * This file is part of the "LLGL" project (Copyright (c) 2015 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "../../GLRenderContext.h"
#include "../../GLExtensions.h"
#include "../../GLExtensionLoader.h"
#include <LLGL/Platform/NativeHandle.h>
#include <LLGL/Log.h>
#include <algorithm>

namespace LLGL
{

void GLRenderContext::Present()
{
    SwapBuffers(context_.hDC);
}

bool GLRenderContext::GLMakeCurrent(GLRenderContext* renderContext)
{
    if (renderContext)
    {
        /* Update new active state manager */
        GLStateManager::active = renderContext->stateMngr_.get();

        /* Make this OpenGL context to the current one */
        const auto& ctx = renderContext->context_;
        return (wglMakeCurrent(ctx.hDC, ctx.hGLRC) == TRUE);
    }
    else
        return (wglMakeCurrent(0, 0) == TRUE);
}

/*
 * ======= Private: =======
 */

static void ErrAntiAliasingNotSupported()
{
    Log::StdErr() << "multi-sample anti-aliasing is not supported" << std::endl;
}

void GLRenderContext::GetNativeContextHandle(NativeContextHandle& windowContext)
{
    windowContext.parentWindow = 0;
}

/*
TODO:
- When anti-aliasing and extended-profile-selection is enabled,
  maximal 2 contexts should be created (and not 3).
*/
void GLRenderContext::CreateContext(GLRenderContext* sharedRenderContext)
{
    /* If a shared context has passed, use its pre-selected pixel format */
    if (desc_.antiAliasing.enabled && sharedRenderContext)
        CopyPixelFormat(*sharedRenderContext);

    /* First setup device context and choose pixel format */
    SetupDeviceContextAndPixelFormat();

    /* Create standard render context first */
    auto stdRenderContext = CreateGLContext(false, sharedRenderContext);

    if (!stdRenderContext)
        throw std::runtime_error("failed to create standard OpenGL render context");

    /* Check for multi-sample anti-aliasing */
    if (desc_.antiAliasing.enabled && !hasSharedContext_)
    {
        /* Setup anti-aliasing after creating a standard render context. */
        if (SetupAntiAliasing())
        {
            /* Delete old standard render context */
            DeleteGLContext(stdRenderContext);

            /*
            For anti-aliasing we must recreate the window,
            because a pixel format can be choosen only once for a Win32 window,
            then update device context and pixel format
            */
            RecreateWindow();

            /* Create a new render context -> now with anti-aliasing pixel format */
            stdRenderContext = CreateGLContext(false, sharedRenderContext);

            if (!stdRenderContext)
                Log::StdErr() << "failed to create multi-sample anti-aliasing" << std::endl;
        }
        else
        {
            /* Print warning and disable anti-aliasing */
            ErrAntiAliasingNotSupported();

            desc_.antiAliasing.enabled = false;
            desc_.antiAliasing.samples = 0;
        }
    }

    context_.hGLRC = stdRenderContext;

    /* Check for extended render context */
    if (desc_.profileOpenGL.extProfile && !hasSharedContext_)
    {
        /*
        Load profile selection extension (wglCreateContextAttribsARB) via current context,
        then create new context with extended settings.
        */
        if (wglCreateContextAttribsARB || LoadCreateContextProcs())
        {
            auto extRenderContext = CreateGLContext(true, sharedRenderContext);

            if (extRenderContext)
            {
                /* Use the extended profile and delete the old standard render context */
                context_.hGLRC = extRenderContext;
                DeleteGLContext(stdRenderContext);
            }
            else
            {
                /* Print warning and disbale profile selection */
                Log::StdErr() << "failed to create extended OpenGL profile" << std::endl;
                desc_.profileOpenGL.extProfile = false;
            }
        }
        else
        {
            /* Print warning and disable profile settings */
            Log::StdErr() << "failed to select OpenGL profile" << std::endl;
            desc_.profileOpenGL.extProfile = false;
        }
    }

    /* Check if context creation was successful */
    if (!context_.hGLRC)
        throw std::runtime_error("failed to create OpenGL render context");

    if (wglMakeCurrent(context_.hDC, context_.hGLRC) != TRUE)
        throw std::runtime_error("failed to activate OpenGL render context");

    /*
    Share resources with previous render context (only for compatibility profile).
    -> Only do this, if this context has its own GL hardware context (hasSharedContext_ == false),
       but a shared render context was passed (sharedRenderContext != null).
    */
    if (sharedRenderContext && !hasSharedContext_ && !desc_.profileOpenGL.extProfile)
    {
        if (!wglShareLists(sharedRenderContext->context_.hGLRC, context_.hGLRC))
            throw std::runtime_error("failed to share resources from OpenGL render context");
    }

    /* Query GL version of final render context */
    //QueryGLVersion();

    /* Setup v-sync interval */
    SetupVSyncInterval();
}

void GLRenderContext::DeleteContext()
{
    if (!hasSharedContext_)
    {
        /* Deactivate context before deletion */
        //Deactivate();
        DeleteGLContext(context_.hGLRC);
    }
}

void GLRenderContext::DeleteGLContext(HGLRC& renderContext)
{
    /* Delete GL render context */
    if (!wglDeleteContext(renderContext))
        Log::StdErr() << "failed to delete OpenGL render context" << std::endl;
    else
        renderContext = 0;
}

HGLRC GLRenderContext::CreateGLContext(bool useExtProfile, GLRenderContext* sharedRenderContext)
{
    /* Create hardware render context */
    HGLRC renderContext = 0;

    if (!sharedRenderContext || !sharedRenderContext->context_.hGLRC /* || createOwnHardwareContext == true*/)
    {
        /* Create own hardware context */
        hasSharedContext_ = false;

        if (useExtProfile)
        {
            renderContext = CreateExtContextProfile(
                (sharedRenderContext != nullptr ? sharedRenderContext->context_.hGLRC : nullptr)
            );
        }
        else
            renderContext = CreateStdContextProfile();
    }
    else
    {
        /* Use shared render context */
        hasSharedContext_ = true;
        renderContext = sharedRenderContext->context_.hGLRC;
    }

    if (!renderContext)
        return 0;

    /* Activate new render context */
    if (wglMakeCurrent(context_.hDC, renderContext) != TRUE)
    {
        /* Print error and delete unusable render context */
        Log::StdErr() << "failed to active OpenGL render context (wglMakeCurrent)" << std::endl;
        DeleteGLContext(renderContext);
        return 0;
    }

    /* Query GL version of current render context */
    //QueryGLVersion();

    return renderContext;
}

HGLRC GLRenderContext::CreateStdContextProfile()
{
    /* Create OpenGL "Compatibility Profile" render context */
    return wglCreateContext(context_.hDC);
}

static void ConvertGLVersion(const OpenGLVersion version, GLint& major, GLint& minor)
{
    if (version == OpenGLVersion::OpenGL_Latest)
    {
        major = 4;
        minor = 5;
    }
    else
    {
        auto ver = static_cast<int>(version);
        major = ver / 100;
        minor = (ver % 100) / 10;
    }
}

HGLRC GLRenderContext::CreateExtContextProfile(HGLRC sharedGLRC)
{
    bool useCoreProfile = desc_.profileOpenGL.coreProfile;

    /* Initialize GL version number */
    GLint major = 0, minor = 0;
    ConvertGLVersion(desc_.profileOpenGL.version, major, minor);

    /* Setup extended attributes to select the OpenGL profile */
    const int attribList[] =
    {
        WGL_CONTEXT_MAJOR_VERSION_ARB,  major,
        WGL_CONTEXT_MINOR_VERSION_ARB,  minor,
        #ifdef LLGL_DEBUG
        WGL_CONTEXT_FLAGS_ARB,          WGL_CONTEXT_DEBUG_BIT_ARB /*| WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB*/,
        #endif
        WGL_CONTEXT_PROFILE_MASK_ARB,   (useCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB),
        0, 0
    };

    /* Create OpenGL "Core Profile" or "Compatibility Profile" render context */
    HGLRC renderContext = wglCreateContextAttribsARB(context_.hDC, sharedGLRC, attribList);

    /* Check for errors */
    DWORD error = GetLastError();

    if (error == ERROR_INVALID_VERSION_ARB)
        Log::StdErr() << "invalid version for OpenGL profile" << std::endl;
    else if (error == ERROR_INVALID_PROFILE_ARB)
        Log::StdErr() << "invalid OpenGL profile" << std::endl;
    else
        return renderContext;

    return 0;
}

void GLRenderContext::SetupDeviceContextAndPixelFormat()
{
    /* Get device context from window */
    NativeHandle nativeHandle;
    GetWindow().GetNativeHandle(&nativeHandle);
    context_.hDC = GetDC(nativeHandle.window);

    /* Select suitable pixel format */
    SelectPixelFormat();
}

void GLRenderContext::SelectPixelFormat()
{
    /* Setup pixel format attributes */
    const auto colorDepth = static_cast<BYTE>(desc_.videoMode.colorDepth);

    PIXELFORMATDESCRIPTOR formatDesc
    {
        sizeof(PIXELFORMATDESCRIPTOR),  // Structure size
        1,                              // Version number
        ( PFD_DRAW_TO_WINDOW |          // Format must support draw-to-window
          PFD_SUPPORT_OPENGL |          // Format must support OpenGL
          PFD_DOUBLEBUFFER   |          // Must support double buffering
          PFD_SWAP_EXCHANGE ),          // Hint to the driver to exchange the back- with the front buffer
        PFD_TYPE_RGBA,                  // Request an RGBA format
        colorDepth,                     // Select color bit depth (cColorBits)
        0, 0, 0, 0, 0, 0,               // Color bits ignored
        8,                              // Request an alpha buffer of 8 bits (cAlphaBits)
        0,                              // Shift bit ignored
        0,                              // No accumulation buffer
        0, 0, 0, 0,                     // Accumulation bits ignored
        24,                             // Z-Buffer bits (cDepthBits)
        1,                              // Stencil buffer bits (cStencilBits)
        0,                              // No auxiliary buffer
        0,                              // Main drawing layer (No longer used)
        0,                              // Reserved
        0, 0, 0                         // Layer masks ignored
    };

    /* Try to find suitable pixel format */
    const bool wantAntiAliasFormat = (desc_.antiAliasing.enabled && !context_.pixelFormatsMS.empty());

    std::size_t msPixelFormatIndex = 0;
    bool wasStandardFormatUsed = false;

    while (true)
    {
        if (wantAntiAliasFormat && msPixelFormatIndex < GLPlatformContext::maxNumPixelFormatsMS)
        {
            /* Choose anti-aliasing pixel format */
            context_.pixelFormat = context_.pixelFormatsMS[msPixelFormatIndex++];
        }

        if (!context_.pixelFormat)
        {
            /* Choose standard pixel format */
            context_.pixelFormat = ChoosePixelFormat(context_.hDC, &formatDesc);

            if (wantAntiAliasFormat)
                ErrAntiAliasingNotSupported();

            wasStandardFormatUsed = true;
        }

        /* Check for errors */
        if (!context_.pixelFormat)
            throw std::runtime_error("failed to select pixel format");

        /* Set pixel format */
        auto wasFormatSelected = SetPixelFormat(context_.hDC, context_.pixelFormat, &formatDesc);

        if (!wasFormatSelected)
        {
            if (wasStandardFormatUsed)
                throw std::runtime_error("failed to set pixel format");
        }
        else
        {
            /* Format was selected -> quit with success */
            break;
        }
    }
}

bool GLRenderContext::SetupAntiAliasing()
{
    /*
    Load GL extension "wglChoosePixelFormatARB" to choose anti-aliasing pixel formats
    A valid (standard) GL context must be created at this time, before an extension can be loaded!
    */
    if (!wglChoosePixelFormatARB && !LoadPixelFormatProcs())
        return false;

    /* Setup pixel format for anti-aliasing */
    const auto queriedMultiSamples = desc_.antiAliasing.samples;

    while (desc_.antiAliasing.samples > 0)
    {
        float attribsFlt[] = { 0.0f, 0.0f };

        int attribsInt[] =
        {
            WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
            WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
            WGL_ACCELERATION_ARB,   WGL_FULL_ACCELERATION_ARB,
            WGL_COLOR_BITS_ARB,     desc_.videoMode.colorDepth,
            WGL_ALPHA_BITS_ARB,     8,
            WGL_DEPTH_BITS_ARB,     24,
            WGL_STENCIL_BITS_ARB,   1,
            WGL_DOUBLE_BUFFER_ARB,  GL_TRUE,
            WGL_SAMPLE_BUFFERS_ARB, (desc_.antiAliasing.enabled ? GL_TRUE : GL_FALSE),
            WGL_SAMPLES_ARB,        static_cast<int>(desc_.antiAliasing.samples),
            0, 0
        };

        /* Choose new pixel format with anti-aliasing */
        UINT numFormats = 0;

        context_.pixelFormatsMS.resize(GLPlatformContext::maxNumPixelFormatsMS);

        int result = wglChoosePixelFormatARB(
            context_.hDC,
            attribsInt,
            attribsFlt,
            GLPlatformContext::maxNumPixelFormatsMS,
            context_.pixelFormatsMS.data(),
            &numFormats
        );

        context_.pixelFormatsMS.resize(numFormats);

        if (!result || numFormats < 1)
        {
            if (desc_.antiAliasing.samples <= 0)
            {
                /* Lowest count of multi-samples reached -> return with error */
                return false;
            }

            /* Choose next lower count of multi-samples */
            --desc_.antiAliasing.samples;
        }
        else
        {
            /* Found suitable pixel formats */
            break;
        }
    }

    /* Check if multi-sample count was reduced */
    if (desc_.antiAliasing.samples < queriedMultiSamples)
    {
        Log::StdOut()
            << "reduced multi-samples for anti-aliasing from "
            << std::to_string(queriedMultiSamples) << " to "
            << std::to_string(desc_.antiAliasing.samples) << std::endl;
    }

    /* Enable anti-aliasing */
    if (desc_.antiAliasing.enabled)
        glEnable(GL_MULTISAMPLE);
    else
        glDisable(GL_MULTISAMPLE);

    return true;
}

void GLRenderContext::CopyPixelFormat(GLRenderContext& sourceContext)
{
    context_.pixelFormat    = sourceContext.context_.pixelFormat;
    context_.pixelFormatsMS = sourceContext.context_.pixelFormatsMS;
}

bool GLRenderContext::SetupVSyncInterval()
{
    /* Load GL extension "wglSwapIntervalEXT" to set v-sync interval */
    if (wglSwapIntervalEXT || LoadSwapIntervalProcs())
    {
        /* Setup v-sync interval */
        int interval = (desc_.vsync.enabled ? static_cast<int>(desc_.vsync.interval) : 0);
        wglSwapIntervalEXT(interval);
        return true;
    }
    return false;
}

void GLRenderContext::RecreateWindow()
{
    /* Recreate window with current descriptor, then update device context and pixel format */
    GetWindow().Recreate(GetWindow().QueryDesc());
    SetupDeviceContextAndPixelFormat();
}

} // /namespace LLGL

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


<commit_before>/* LiteSQL
 *
 * The list of contributors at http://litesql.sf.net/
 *
 * See LICENSE for copyright information. */

#ifndef litesql_field_hpp
#define litesql_field_hpp
#include <iostream>
#include <vector>
#include <utility>
#include <string>
#include "litesql/string.hpp"

/** \file field.hpp
    contains FieldType- and Field-classes */
namespace litesql {
using namespace std;

/** holds field name, type and table information */
class In;
class Like;
class SelectQuery;

class FieldType {
    string _name, _type, _table;

protected:
    typedef vector< pair<string, string> > Values;
private:
    Values _values;
public:

    FieldType(const string& n,
              const string& t,
              const string& tbl,
              const Values& vals = Values())
        : _name(n), _type(t), _table(tbl), _values(vals) {}
    string fullName() const { return  table() + "." + name(); }
    string name() const { return _name; }
    string type() const { return _type; }
    string table() const { return _table; }
    vector< pair<string, string> > values() { return _values; }
    /** syntactic sugar to Expr-API, Object::field_.in(set) */
    In in(const string& set) const;
    /** syntactic sugar to Expr-API, Object::field_.in(sel) */
    In in(const SelectQuery& sel) const;
    /** syntactic sugar to Expr-API, Object::field_.like(s) */
    Like like(const string& s);
    bool operator==(const FieldType & fd) const {
        return fd.fullName() == fullName();
    }
    bool operator!=(const FieldType & fd) const {
        return ! (*this == fd);
    }
};

/** convert function */
template <class From, class To>
To convert(From value);

/** store function */
template <class T>
std::string store(const T& value) {
    return litesql::toString(value);
}

template <class T>
T load(const std::string& value) {
    return convert<const std::string&, T>(value);
}
/** holds field value */
template <class T>
class Field {
    const FieldType * field;
    bool _modified;
    T _value;
public:
    Field(const FieldType & f) : field(&f), _modified(true) {}
    string fullName() const { return field->fullName(); }
    string name() const { return field->name(); }
    string type() const { return field->type(); }
    string table() const { return field->table(); }
    T value() const { return _value; }
    const FieldType & fieldType() const { return *field; }
    bool modified() const { return _modified; }
    void setModified(bool state) { _modified = state; }
    const Field & operator=(const string& v) {
        _value = convert<const string&, T>(v);
        _modified = true;
        return *this;
    }
    const Field & operator=(const T& v) {
        _value = v;
        _modified = true;
        return *this;
    }
    template <class T2>
    const Field & operator=(T2 v) {
        _modified = true;
        _value = litesql::convert<T2, T>(v);
        return *this;
    }
    template <class T2>
    bool operator==(const T2& v) const {
        return litesql::toString(_value) == litesql::toString(v);
    }
    template <class T2>
    bool operator!=(const T2& v) const { return !(*this == v); }

    operator string() const { return toString(value()); }

    operator T() const { return value(); }
};

template <>
class Field<string> {
    const FieldType * field;
    bool _modified;
    string _value;
public:
    Field(const FieldType & f) : field(&f), _modified(true) {}
    string fullName() const { return field->fullName(); }
    string name() const { return field->name(); }
    string type() const { return field->type(); }
    string table() const { return field->table(); }
    string value() const { return _value; }
    const FieldType & fieldType() const { return *field; }
    bool modified() const { return _modified; }
    void setModified(bool state) { _modified = state; }
    const Field & operator=(string v) {
        _value = v;
        _modified = true;
        return *this;
    }
    const Field& operator=(const char * v) {
        _value = v;
        _modified = true;
        return *this;
    }
    template <class T2>
    const Field & operator=(T2 v) {
        _modified = true;
        _value = litesql::convert<T2, string>(v);
        return *this;
    }
    template <class T2>
    bool operator==(const T2& v) const {
        return litesql::toString(_value) == litesql::toString(v);
    }
    template <class T2>
    bool operator!=(const T2& v) const { return !(*this == v); }

    operator string() const { return value(); }
};

typedef unsigned char u8_t;

class Blob {
public:
  Blob()                            : m_data(NULL),m_length(0)               {};
  Blob(const string & value) : m_data(NULL),m_length(0)
  {
    initWithHexString(value);
  };

  Blob(const Blob & b) : m_data(NULL)
  {
    initWithData(b.m_data,b.m_length);
  };

  Blob(const void* data, size_t length) : m_data(NULL), m_length(0)
  {
    initWithData((u8_t*)data,length);
  };

  virtual ~Blob();
  const Blob& operator=(const Blob& v) {
    initWithData(v.m_data,v.m_length);
    return *this;
  }

  string toHex()            const ;
  size_t length()           const  { return m_length;      };
  bool   isNull()           const  { return m_data==NULL;  };
  u8_t   data(size_t index) const  { return m_data[index]; };
  void   data(const char* pszData);
private:
  u8_t* m_data;
  size_t m_length;

  void initWithData(const u8_t* data, size_t length);
  void initWithHexString(const string& hexString);
};

ostream& operator << (ostream& os, const Blob& blob);
template <>
Blob convert<const string&, Blob>(const string& value);
template <>
string convert<const Blob&, string>(const Blob& value);

template <>
class Field<Blob> {
    const FieldType * field;
    bool _modified;
    Blob _value;
public:
    Field(const FieldType & f) : field(&f), _modified(true) {}
    string fullName() const { return field->fullName(); }
    string name() const { return field->name(); }
    string type() const { return field->type(); }
    string table() const { return field->table(); }
    Blob value() const { return _value; }
    const FieldType & fieldType() const { return *field; }
    bool modified() const { return _modified; }
    void setModified(bool state) { _modified = state; }
    const Field & operator=(const Blob& v) {
        _value = v;
        _modified = true;
        return *this;
    }

const Field & operator=(int v) {
        _value.data(NULL);
        _modified = true;
        return *this;
    }

/*
const Field& operator=(const char * v) {
        _value = v;
        _modified = true;
        return *this;
    }
    template <class T2>
    const Field & operator=(T2 v) {
        _modified = true;
        _value = litesql::convert<T2, Blob>(v);
        return *this;
    }
    template <class T2>
    bool operator==(const T2& v) const {
        return litesql::toString(_value) == litesql::toString(v);
    }
    template <class T2>
    bool operator!=(const T2& v) const { return !(*this == v); }
*/

    operator string() const { return _value.toHex(); }
};

template <class T>
std::string operator+(std::string a, litesql::Field<T> f) {
    return a + std::string(f);
}
template <class T>
std::string operator+(litesql::Field<T> f, std::string a) {
    return std::string(f) + a;
}
template <class T>
std::ostream & operator << (std::ostream & os, const litesql::Field<T> & f) {
    return os << f.value();
}

}
#endif
<commit_msg>added private default constructor (hopefully a fix for trac #27)<commit_after>/* LiteSQL
 *
 * The list of contributors at http://litesql.sf.net/
 *
 * See LICENSE for copyright information. */

#ifndef litesql_field_hpp
#define litesql_field_hpp
#include <iostream>
#include <vector>
#include <utility>
#include <string>
#include "litesql/string.hpp"

/** \file field.hpp
    contains FieldType- and Field-classes */
namespace litesql {
using namespace std;

/** holds field name, type and table information */
class In;
class Like;
class SelectQuery;

class FieldType {
    string _name, _type, _table;

protected:
    typedef vector< pair<string, string> > Values;
private:
    Values _values;
    FieldType() {};
public:

    FieldType(const string& n,
              const string& t,
              const string& tbl,
              const Values& vals = Values())
        : _name(n), _type(t), _table(tbl), _values(vals) {}
    string fullName() const { return  table() + "." + name(); }
    string name() const { return _name; }
    string type() const { return _type; }
    string table() const { return _table; }
    vector< pair<string, string> > values() { return _values; }
    /** syntactic sugar to Expr-API, Object::field_.in(set) */
    In in(const string& set) const;
    /** syntactic sugar to Expr-API, Object::field_.in(sel) */
    In in(const SelectQuery& sel) const;
    /** syntactic sugar to Expr-API, Object::field_.like(s) */
    Like like(const string& s);
    bool operator==(const FieldType & fd) const {
        return fd.fullName() == fullName();
    }
    bool operator!=(const FieldType & fd) const {
        return ! (*this == fd);
    }
};

/** convert function */
template <class From, class To>
To convert(From value);

/** store function */
template <class T>
std::string store(const T& value) {
    return litesql::toString(value);
//  return convert<T,std::string>(value);
}

template <class T>
T load(const std::string& value) {
    return convert<const std::string&, T>(value);
}
/** holds field value */
template <class T>
class Field {
    const FieldType * field;
    bool _modified;
    T _value;
public:
    Field(const FieldType & f) : field(&f), _modified(true) {}
    string fullName() const { return field->fullName(); }
    string name() const { return field->name(); }
    string type() const { return field->type(); }
    string table() const { return field->table(); }
    T value() const { return _value; }
    const FieldType & fieldType() const { return *field; }
    bool modified() const { return _modified; }
    void setModified(bool state) { _modified = state; }
    const Field & operator=(const string& v) {
        _value = convert<const string&, T>(v);
        _modified = true;
        return *this;
    }
    const Field & operator=(const T& v) {
        _value = v;
        _modified = true;
        return *this;
    }
    template <class T2>
    const Field & operator=(T2 v) {
        _modified = true;
        _value = litesql::convert<T2, T>(v);
        return *this;
    }
    template <class T2>
    bool operator==(const T2& v) const {
        return litesql::toString(_value) == litesql::toString(v);
    }
    template <class T2>
    bool operator!=(const T2& v) const { return !(*this == v); }

    operator string() const { return toString(value()); }

    operator T() const { return value(); }
};

template <>
class Field<string> {
    const FieldType * field;
    bool _modified;
    string _value;
public:
    Field(const FieldType & f) : field(&f), _modified(true) {}
    string fullName() const { return field->fullName(); }
    string name() const { return field->name(); }
    string type() const { return field->type(); }
    string table() const { return field->table(); }
    string value() const { return _value; }
    const FieldType & fieldType() const { return *field; }
    bool modified() const { return _modified; }
    void setModified(bool state) { _modified = state; }
    const Field & operator=(string v) {
        _value = v;
        _modified = true;
        return *this;
    }
    const Field& operator=(const char * v) {
        _value = v;
        _modified = true;
        return *this;
    }
    template <class T2>
    const Field & operator=(T2 v) {
        _modified = true;
        _value = litesql::convert<T2, string>(v);
        return *this;
    }
    template <class T2>
    bool operator==(const T2& v) const {
        return litesql::toString(_value) == litesql::toString(v);
    }
    template <class T2>
    bool operator!=(const T2& v) const { return !(*this == v); }

    operator string() const { return value(); }
};

typedef unsigned char u8_t;

class Blob {
public:
  Blob()                            : m_data(NULL),m_length(0)               {};
  Blob(const string & value) : m_data(NULL),m_length(0)
  {
    initWithHexString(value);
  };

  Blob(const Blob & b) : m_data(NULL)
  {
    initWithData(b.m_data,b.m_length);
  };

  Blob(const void* data, size_t length) : m_data(NULL), m_length(0)
  {
    initWithData((u8_t*)data,length);
  };

  virtual ~Blob();
  const Blob& operator=(const Blob& v) {
    initWithData(v.m_data,v.m_length);
    return *this;
  }

  string toHex()            const ;
  size_t length()           const  { return m_length;      };
  bool   isNull()           const  { return m_data==NULL;  };
  u8_t   data(size_t index) const  { return m_data[index]; };
  void   data(const char* pszData);
private:
  u8_t* m_data;
  size_t m_length;

  void initWithData(const u8_t* data, size_t length);
  void initWithHexString(const string& hexString);
};

ostream& operator << (ostream& os, const Blob& blob);
template <>
Blob convert<const string&, Blob>(const string& value);
template <>
string convert<const Blob&, string>(const Blob& value);

template <>
class Field<Blob> {
    const FieldType * field;
    bool _modified;
    Blob _value;
public:
    Field(const FieldType & f) : field(&f), _modified(true) {}
    string fullName() const { return field->fullName(); }
    string name() const { return field->name(); }
    string type() const { return field->type(); }
    string table() const { return field->table(); }
    Blob value() const { return _value; }
    const FieldType & fieldType() const { return *field; }
    bool modified() const { return _modified; }
    void setModified(bool state) { _modified = state; }
    const Field & operator=(const Blob& v) {
        _value = v;
        _modified = true;
        return *this;
    }

const Field & operator=(int v) {
        _value.data(NULL);
        _modified = true;
        return *this;
    }

/*
const Field& operator=(const char * v) {
        _value = v;
        _modified = true;
        return *this;
    }
    template <class T2>
    const Field & operator=(T2 v) {
        _modified = true;
        _value = litesql::convert<T2, Blob>(v);
        return *this;
    }
    template <class T2>
    bool operator==(const T2& v) const {
        return litesql::toString(_value) == litesql::toString(v);
    }
    template <class T2>
    bool operator!=(const T2& v) const { return !(*this == v); }
*/

    operator string() const { return _value.toHex(); }
};

template <class T>
std::string operator+(std::string a, litesql::Field<T> f) {
    return a + std::string(f);
}
template <class T>
std::string operator+(litesql::Field<T> f, std::string a) {
    return std::string(f) + a;
}
template <class T>
std::ostream & operator << (std::ostream & os, const litesql::Field<T> & f) {
    return os << f.value();
}

}
#endif
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "disc_brawling.h"

CDBrawling::CDBrawling() :
  CDiscipline(),
  skGrapple(),
  skStomp(),
  skBrawlAvoidance(),
  skBodyslam(),
  skSpin(),
  skCloseQuartersFighting(),
  skTaunt()
{
}

CDBrawling::CDBrawling(const CDBrawling &a) :
  CDiscipline(a),
  skGrapple(a.skGrapple),
  skStomp(a.skStomp),
  skBrawlAvoidance(a.skBrawlAvoidance),
  skBodyslam(a.skBodyslam),
  skSpin(a.skSpin),
  skCloseQuartersFighting(a.skCloseQuartersFighting),
  skTaunt(a.skTaunt)
{
}

CDBrawling & CDBrawling::operator=(const CDBrawling &a)
{
  if (this == &a) return *this;
  CDiscipline::operator=(a);
  skGrapple = a.skGrapple;
  skStomp = a.skStomp;
  skBrawlAvoidance = a.skBrawlAvoidance;
  skBodyslam = a.skBodyslam;
  skSpin = a.skSpin;
  skCloseQuartersFighting = a.skCloseQuartersFighting;
  skTaunt = a.skTaunt;
  return *this;
}

CDBrawling::~CDBrawling()
{
}

int TBeing::doTaunt(const sstring &arg)
{
  TBeing *victim;
  char name_buf[256];

  strcpy(name_buf, arg.c_str());

  if (!(victim = get_char_room_vis(this, name_buf))) {
    if (!(victim = fight())) {
      sendTo("Taunt whom?\n\r");
      return FALSE;
    }
  }
  if (!sameRoom(*victim)) {
    sendTo("That person isn't around.\n\r");
    return FALSE;
  }

  if(!doesKnowSkill(SKILL_TAUNT) ||
     (roomp && roomp->isRoomFlag(ROOM_PEACEFUL)) ||
     victim==this || noHarmCheck(victim) || checkBusy() ||
     victim->isDumbAnimal() || !canSpeak() || victim != fight()){
    return doAction(arg, CMD_TAUNT);
  }

  if(bSuccess(SKILL_TAUNT)){
    act("You taunt $N ruthlessly, drawing their ire.",
	FALSE, this, 0, victim, TO_CHAR);
    act("$n taunts you ruthlessly, drawing your ire.",
	FALSE, this, 0, victim, TO_VICT);
    act("$n taunts $N ruthlessly, drawing their ire.",
	FALSE, this, 0, victim, TO_NOTVICT);

    affectedData af;

    af.type = SKILL_TAUNT;
    af.level = getSkillValue(SKILL_TAUNT);
    af.duration = PULSE_COMBAT * ::number(1, (int)(af.level/10));// 1-10 rounds
    af.location = APPLY_NONE;
    af.modifier = 0;
    af.bitvector = 0;
    victim->affectFrom(SKILL_TAUNT);
    victim->affectTo(&af, -1);

    addSkillLag(SKILL_TAUNT, 0);
  }

  return TRUE;
}
<commit_msg>added fail message for taunt<commit_after>//////////////////////////////////////////////////////////////////////////
//
// SneezyMUD - All rights reserved, SneezyMUD Coding Team
//
//////////////////////////////////////////////////////////////////////////

#include "stdsneezy.h"
#include "disc_brawling.h"

CDBrawling::CDBrawling() :
  CDiscipline(),
  skGrapple(),
  skStomp(),
  skBrawlAvoidance(),
  skBodyslam(),
  skSpin(),
  skCloseQuartersFighting(),
  skTaunt()
{
}

CDBrawling::CDBrawling(const CDBrawling &a) :
  CDiscipline(a),
  skGrapple(a.skGrapple),
  skStomp(a.skStomp),
  skBrawlAvoidance(a.skBrawlAvoidance),
  skBodyslam(a.skBodyslam),
  skSpin(a.skSpin),
  skCloseQuartersFighting(a.skCloseQuartersFighting),
  skTaunt(a.skTaunt)
{
}

CDBrawling & CDBrawling::operator=(const CDBrawling &a)
{
  if (this == &a) return *this;
  CDiscipline::operator=(a);
  skGrapple = a.skGrapple;
  skStomp = a.skStomp;
  skBrawlAvoidance = a.skBrawlAvoidance;
  skBodyslam = a.skBodyslam;
  skSpin = a.skSpin;
  skCloseQuartersFighting = a.skCloseQuartersFighting;
  skTaunt = a.skTaunt;
  return *this;
}

CDBrawling::~CDBrawling()
{
}

int TBeing::doTaunt(const sstring &arg)
{
  TBeing *victim;
  char name_buf[256];

  strcpy(name_buf, arg.c_str());

  if (!(victim = get_char_room_vis(this, name_buf))) {
    if (!(victim = fight())) {
      sendTo("Taunt whom?\n\r");
      return FALSE;
    }
  }
  if (!sameRoom(*victim)) {
    sendTo("That person isn't around.\n\r");
    return FALSE;
  }

  if(!doesKnowSkill(SKILL_TAUNT) ||
     (roomp && roomp->isRoomFlag(ROOM_PEACEFUL)) ||
     victim==this || noHarmCheck(victim) || checkBusy() ||
     victim->isDumbAnimal() || !canSpeak() || victim != fight()){
    return doAction(arg, CMD_TAUNT);
  }

  if(bSuccess(SKILL_TAUNT)){
    act("You taunt $N ruthlessly, drawing their ire.",
	FALSE, this, 0, victim, TO_CHAR);
    act("$n taunts you ruthlessly, drawing your ire.",
	FALSE, this, 0, victim, TO_VICT);
    act("$n taunts $N ruthlessly, drawing their ire.",
	FALSE, this, 0, victim, TO_NOTVICT);

    affectedData af;

    af.type = SKILL_TAUNT;
    af.level = getSkillValue(SKILL_TAUNT);
    af.duration = PULSE_COMBAT * ::number(1, (int)(af.level/10));// 1-10 rounds
    af.location = APPLY_NONE;
    af.modifier = 0;
    af.bitvector = 0;
    victim->affectFrom(SKILL_TAUNT);
    victim->affectTo(&af, -1);

  } else {
    act("You taunt yourself ruthlessly, confusing yourself.",
	FALSE, this, 0, this, TO_CHAR);
    act("$n taunts $mself ruthlessly, confusing $mself.",
	FALSE, this, 0, this, TO_NOTVICT);
  }

  addSkillLag(SKILL_TAUNT, 0);

  return TRUE;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

using namespace std;

int main()
{
	system("color 70");
	setlocale(0, "Russina");
	SetConsoleTitle("031.STL_ReverseReverse_Copy");

	vector<int> vec{ 0,1,2,3,4,5,6,7,8,9 };

	cout << "Vector befor reverse:" << endl;

	for (auto i : vec)
		cout << i << " ";
	cout << endl;

	//reverse
	reverse(vec.begin(), vec.end());

	cout << "Vector after reverse:" << endl;

	for (auto i : vec)
		cout << i << " ";
	cout << endl;

	vector<int> vec2(10);

	cout << "Vector 2 befor reverse_copy:" << endl;

	for (auto i : vec2)
		cout << i << " ";
	cout << endl;

	//reverse_copy
	//
	reverse_copy(vec.begin(), vec.end(), vec2.begin());

	cout << "Vector 2 befor reverse_copy:" << endl;

	for (auto i : vec2)
		cout << i << " ";
	cout << endl;

	system("pause");
    return 0;
}

<commit_msg>Change encoding.<commit_after>#include "stdafx.h"

using namespace std;

int main()
{
	system("color 70");
	setlocale(0, "Russina");
	SetConsoleTitle("031.STL_ReverseReverse_Copy");

	vector<int> vec{ 0,1,2,3,4,5,6,7,8,9 };

	cout << "Vector befor reverse:" << endl;

	for (auto i : vec)
		cout << i << " ";
	cout << endl;

	//reverse изменяет порядок элементов на противоположный
	reverse(vec.begin(), vec.end());

	cout << "Vector after reverse:" << endl;

	for (auto i : vec)
		cout << i << " ";
	cout << endl;

	vector<int> vec2(10);

	cout << "Vector 2 befor reverse_copy:" << endl;

	for (auto i : vec2)
		cout << i << " ";
	cout << endl;

	//reverse_copy копирует диапазон в другое место при этом
	//меняет порядок элементов на противоположный
	reverse_copy(vec.begin(), vec.end(), vec2.begin());

	cout << "Vector 2 befor reverse_copy:" << endl;

	for (auto i : vec2)
		cout << i << " ";
	cout << endl;

	system("pause");
    return 0;
}

<|endoftext|>


<commit_before>#include "InternetCommDevice.h"
#include <QDebug>

void InternetCommDevice::setQueueName(QString queueName)
{
    queueName_ = queueName;
}

void InternetCommDevice::setChannel(AmqpClient::Channel::ptr_t channel)
{
    channel_ = channel;
}

void InternetCommDevice::run()
{
    while (1)
    {
        std::string consumer_tag = channel_->BasicConsume(queueName_.toStdString(), "", true, true, false);
        AmqpClient::Envelope::ptr_t envelope = channel_->BasicConsumeMessage(consumer_tag);
        QString str = QString::fromStdString(envelope->Message()->Body());
        QByteArray dat = str.toUtf8();

        qDebug("New data has been received");

        emit dataReceived(dat);
    }
}
<commit_msg>Fix retrieving messages<commit_after>#include "InternetCommDevice.h"
#include <QDebug>

void InternetCommDevice::setQueueName(QString queueName)
{
    queueName_ = queueName;
}

void InternetCommDevice::setChannel(AmqpClient::Channel::ptr_t channel)
{
    channel_ = channel;
}

void InternetCommDevice::run()
{
    std::string consumer_tag = channel_->BasicConsume(queueName_.toStdString(), "", true, true, false);

    while (1)
    {
        AmqpClient::Envelope::ptr_t envelope = channel_->BasicConsumeMessage(consumer_tag);
        QString str = QString::fromStdString(envelope->Message()->Body());
        QByteArray dat = str.toUtf8();

        qDebug("New data has been received");

        emit dataReceived(dat);
    }
}
<|endoftext|>


<commit_before>#include "SDLWindow.h"
#include "SDLRenderer.h"
#include "../../graphics/opengl/OpenGL.h"
#include "../../graphics/opengl/OpenGLBindings.h"

namespace lime {

	SDLRenderer::SDLRenderer (Window* window) {

		currentWindow = window;
		sdlWindow = ((SDLWindow*)window)->sdlWindow;
		sdlTexture = 0;
		context = 0;

		width = 0;
		height = 0;

		int sdlFlags = 0;

		if (window->flags & WINDOW_FLAG_HARDWARE) {

			sdlFlags |= SDL_RENDERER_ACCELERATED;

			if (window->flags & WINDOW_FLAG_VSYNC) {

				sdlFlags |= SDL_RENDERER_PRESENTVSYNC;

			}

		} else {

			sdlFlags |= SDL_RENDERER_SOFTWARE;

		}

		sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags);

		if (sdlFlags & SDL_RENDERER_ACCELERATED) {

			if (sdlRenderer) {

				bool valid = false;
				context = SDL_GL_GetCurrentContext ();

				if (context) {

					OpenGLBindings::Init ();

					#ifndef LIME_GLES
					int version = 0;
					glGetIntegerv (GL_MAJOR_VERSION, &version);

					if (version == 0) {

						float versionScan = 0;
						sscanf ((const char*)glGetString (GL_VERSION), "%f", &versionScan);
						version = versionScan;

					}

					if (version >= 2 || strstr ((const char*)glGetString (GL_VERSION), "OpenGL ES")) {

						valid = true;

					}
					#else
					valid = true;
					#endif

					#ifdef IPHONEOS
					glGetIntegerv (GL_FRAMEBUFFER_BINDING_OES, &OpenGLBindings::defaultFramebuffer);
					#endif

				}

				if (!valid) {

					SDL_DestroyRenderer (sdlRenderer);
					sdlRenderer = 0;

				}

			}

			if (!sdlRenderer) {

				sdlFlags &= ~SDL_RENDERER_ACCELERATED;
				sdlFlags &= ~SDL_RENDERER_PRESENTVSYNC;

				sdlFlags |= SDL_RENDERER_SOFTWARE;

				sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags);

			}

		}

		if (!sdlRenderer) {

			printf ("Could not create SDL renderer: %s.\n", SDL_GetError ());

		}

	}

	SDLRenderer::~SDLRenderer () {

		if (sdlRenderer) {

			SDL_DestroyRenderer (sdlRenderer);

		}

	}

	void SDLRenderer::Flip () {

		SDL_RenderPresent (sdlRenderer);

	}

	void* SDLRenderer::GetContext () {

		return context;

	}

	double SDLRenderer::GetScale () {

		int outputWidth;
		int outputHeight;

		SDL_GetRendererOutputSize (sdlRenderer, &outputWidth, &outputHeight);

		int width;
		int height;

		SDL_GetWindowSize (sdlWindow, &width, &height);

		double scale = double (outputWidth) / width;
		return scale;

	}

	value SDLRenderer::Lock () {

		int width;
		int height;

		SDL_GetRendererOutputSize (sdlRenderer, &width, &height);

		if (width != this->width || height != this->height) {

			if (sdlTexture) {

				SDL_DestroyTexture (sdlTexture);

			}

			sdlTexture = SDL_CreateTexture (sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);

		}

		value result = alloc_empty_object ();

		void *pixels;
		int pitch;

		if (SDL_LockTexture (sdlTexture, NULL, &pixels, &pitch) == 0) {

			alloc_field (result, val_id ("width"), alloc_int (width));
			alloc_field (result, val_id ("height"), alloc_int (height));
			alloc_field (result, val_id ("pixels"), alloc_float ((uintptr_t)pixels));
			alloc_field (result, val_id ("pitch"), alloc_int (pitch));

		}

		return result;

	}

	void SDLRenderer::MakeCurrent () {

		if (sdlWindow && context) {

			SDL_GL_MakeCurrent (sdlWindow, context);

		}

	}

	void SDLRenderer::ReadPixels (ImageBuffer *buffer, Rectangle *rect) {

		if (sdlRenderer) {

			SDL_Rect bounds = { 0, 0, 0, 0 };

			if (rect) {

				bounds.x = rect->x;
				bounds.y = rect->y;
				bounds.w = rect->width;
				bounds.h = rect->height;

			} else {

				SDL_GetWindowSize (sdlWindow, &bounds.w, &bounds.h);

			}

			buffer->Resize (bounds.w, bounds.h, 32);

			SDL_RenderReadPixels (sdlRenderer, &bounds, SDL_PIXELFORMAT_ABGR8888, buffer->data->Data (), buffer->Stride ());

			for (unsigned char *it=buffer->data->Data () + 3; it < (buffer->data->Data () + buffer->data->Length ()); it += 4) {

				*it = 0xff;

			}

		}

	}

	const char* SDLRenderer::Type () {

		if (sdlRenderer) {

			SDL_RendererInfo info;
			SDL_GetRendererInfo (sdlRenderer, &info);

			if (info.flags & SDL_RENDERER_SOFTWARE) {

				return "software";

			} else {

				return "opengl";

			}

		}

		return "none";

	}

	void SDLRenderer::Unlock () {

		if (sdlTexture) {

			SDL_UnlockTexture (sdlTexture);
			SDL_RenderClear (sdlRenderer);
			SDL_RenderCopy (sdlRenderer, sdlTexture, NULL, NULL);

		}

	}

	Renderer* CreateRenderer (Window* window) {

		return new SDLRenderer (window);

	}

}<commit_msg>Do not force renderer.readPixels to be opaque on native<commit_after>#include "SDLWindow.h"
#include "SDLRenderer.h"
#include "../../graphics/opengl/OpenGL.h"
#include "../../graphics/opengl/OpenGLBindings.h"

namespace lime {

	SDLRenderer::SDLRenderer (Window* window) {

		currentWindow = window;
		sdlWindow = ((SDLWindow*)window)->sdlWindow;
		sdlTexture = 0;
		context = 0;

		width = 0;
		height = 0;

		int sdlFlags = 0;

		if (window->flags & WINDOW_FLAG_HARDWARE) {

			sdlFlags |= SDL_RENDERER_ACCELERATED;

			if (window->flags & WINDOW_FLAG_VSYNC) {

				sdlFlags |= SDL_RENDERER_PRESENTVSYNC;

			}

		} else {

			sdlFlags |= SDL_RENDERER_SOFTWARE;

		}

		sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags);

		if (sdlFlags & SDL_RENDERER_ACCELERATED) {

			if (sdlRenderer) {

				bool valid = false;
				context = SDL_GL_GetCurrentContext ();

				if (context) {

					OpenGLBindings::Init ();

					#ifndef LIME_GLES
					int version = 0;
					glGetIntegerv (GL_MAJOR_VERSION, &version);

					if (version == 0) {

						float versionScan = 0;
						sscanf ((const char*)glGetString (GL_VERSION), "%f", &versionScan);
						version = versionScan;

					}

					if (version >= 2 || strstr ((const char*)glGetString (GL_VERSION), "OpenGL ES")) {

						valid = true;

					}
					#else
					valid = true;
					#endif

					#ifdef IPHONEOS
					glGetIntegerv (GL_FRAMEBUFFER_BINDING_OES, &OpenGLBindings::defaultFramebuffer);
					#endif

				}

				if (!valid) {

					SDL_DestroyRenderer (sdlRenderer);
					sdlRenderer = 0;

				}

			}

			if (!sdlRenderer) {

				sdlFlags &= ~SDL_RENDERER_ACCELERATED;
				sdlFlags &= ~SDL_RENDERER_PRESENTVSYNC;

				sdlFlags |= SDL_RENDERER_SOFTWARE;

				sdlRenderer = SDL_CreateRenderer (sdlWindow, -1, sdlFlags);

			}

		}

		if (!sdlRenderer) {

			printf ("Could not create SDL renderer: %s.\n", SDL_GetError ());

		}

	}

	SDLRenderer::~SDLRenderer () {

		if (sdlRenderer) {

			SDL_DestroyRenderer (sdlRenderer);

		}

	}

	void SDLRenderer::Flip () {

		SDL_RenderPresent (sdlRenderer);

	}

	void* SDLRenderer::GetContext () {

		return context;

	}

	double SDLRenderer::GetScale () {

		int outputWidth;
		int outputHeight;

		SDL_GetRendererOutputSize (sdlRenderer, &outputWidth, &outputHeight);

		int width;
		int height;

		SDL_GetWindowSize (sdlWindow, &width, &height);

		double scale = double (outputWidth) / width;
		return scale;

	}

	value SDLRenderer::Lock () {

		int width;
		int height;

		SDL_GetRendererOutputSize (sdlRenderer, &width, &height);

		if (width != this->width || height != this->height) {

			if (sdlTexture) {

				SDL_DestroyTexture (sdlTexture);

			}

			sdlTexture = SDL_CreateTexture (sdlRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, width, height);

		}

		value result = alloc_empty_object ();

		void *pixels;
		int pitch;

		if (SDL_LockTexture (sdlTexture, NULL, &pixels, &pitch) == 0) {

			alloc_field (result, val_id ("width"), alloc_int (width));
			alloc_field (result, val_id ("height"), alloc_int (height));
			alloc_field (result, val_id ("pixels"), alloc_float ((uintptr_t)pixels));
			alloc_field (result, val_id ("pitch"), alloc_int (pitch));

		}

		return result;

	}

	void SDLRenderer::MakeCurrent () {

		if (sdlWindow && context) {

			SDL_GL_MakeCurrent (sdlWindow, context);

		}

	}

	void SDLRenderer::ReadPixels (ImageBuffer *buffer, Rectangle *rect) {

		if (sdlRenderer) {

			SDL_Rect bounds = { 0, 0, 0, 0 };

			if (rect) {

				bounds.x = rect->x;
				bounds.y = rect->y;
				bounds.w = rect->width;
				bounds.h = rect->height;

			} else {

				SDL_GetWindowSize (sdlWindow, &bounds.w, &bounds.h);

			}

			buffer->Resize (bounds.w, bounds.h, 32);

			SDL_RenderReadPixels (sdlRenderer, &bounds, SDL_PIXELFORMAT_ABGR8888, buffer->data->Data (), buffer->Stride ());

		}

	}

	const char* SDLRenderer::Type () {

		if (sdlRenderer) {

			SDL_RendererInfo info;
			SDL_GetRendererInfo (sdlRenderer, &info);

			if (info.flags & SDL_RENDERER_SOFTWARE) {

				return "software";

			} else {

				return "opengl";

			}

		}

		return "none";

	}

	void SDLRenderer::Unlock () {

		if (sdlTexture) {

			SDL_UnlockTexture (sdlTexture);
			SDL_RenderClear (sdlRenderer);
			SDL_RenderCopy (sdlRenderer, sdlTexture, NULL, NULL);

		}

	}

	Renderer* CreateRenderer (Window* window) {

		return new SDLRenderer (window);

	}

}<|endoftext|>